BZOJ3888 [Usaco2015 Jan]Stampede

我们只要把每头牛开始遮挡视线和结束遮挡视线的时间点都搞出来就好= =

再按照y轴排序。。。然后变成线段覆盖了。。线段树搞一下就好了?

  1 /**************************************************************
  2     Problem: 3888
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:1204 ms
  7     Memory:22684 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <algorithm>
 12
 13 using namespace std;
 14 const int N = 1e5 + 5;
 15
 16 struct data {
 17     int x, y, c;
 18     int st, ed;
 19
 20     inline void read() {
 21         scanf("%d%d%d", &x, &y, &c);
 22         x *= -1, st = c * (x - 1), ed = st + c;
 23     }
 24
 25     inline bool operator < (const data &p) const {
 26         return y > p.y;
 27     }
 28 } a[N];
 29
 30 struct seg_node {
 31     seg_node *ls, *rs;
 32     int v;
 33 } *seg_null, *seg_root, mempool[N << 4], *cnt_seg = mempool;
 34
 35 int n, ans;
 36 int v[N];
 37 int t[N << 1], tot;
 38
 39 #define Ls p -> ls
 40 #define Rs p -> rs
 41 #define V p -> v
 42 #define mid (l + r >> 1)
 43 inline void seg_get_null(seg_node *&p) {
 44     p = cnt_seg, Ls = Rs = p;
 45 }
 46
 47 inline void seg_new(seg_node *&p) {
 48     p = ++cnt_seg, *p = *seg_null;
 49 }
 50
 51 inline void seg_push(seg_node *p) {
 52     if (V) {
 53         Ls -> v = Rs -> v = V;
 54         V = 0;
 55     }
 56 }
 57
 58 inline void seg_build(seg_node *&p, int l, int r) {
 59     seg_new(p);
 60     if (l == r) return;
 61     seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r);
 62 }
 63
 64 inline void seg_modify(seg_node *p, int l, int r, int L, int R, int v) {
 65     if (L <= l && r <= R) {
 66         V = v;
 67         return;
 68     }
 69     seg_push(p);
 70     if (L <= mid) seg_modify(Ls, l, mid, L, R, v);
 71     if (mid < R) seg_modify(Rs, mid + 1, r, L, R, v);
 72 }
 73
 74 inline int seg_query(seg_node *p, int l, int r, int pos) {
 75     if (l == r) return V;
 76     seg_push(p);
 77     if (pos <= mid) return seg_query(Ls, l, mid, pos);
 78     else return seg_query(Rs, mid + 1, r, pos);
 79 }
 80 #undef Ls
 81 #undef Rs
 82 #undef V
 83 #undef mid
 84
 85 int main() {
 86     int i;
 87     scanf("%d", &n);
 88     for (i = 1; i <= n; ++i)
 89         a[i].read();
 90     sort(a + 1, a + n + 1);
 91     for (i = 1; i <= n; ++i)
 92         t[i * 2 - 1] = a[i].st, t[i * 2] = a[i].ed;
 93     sort(t + 1, t + 2 * n + 1);
 94     tot = unique(t + 1, t + 2 * n + 1) - t;
 95     for (i = 1; i <= n; ++i) {
 96         a[i].st = lower_bound(t + 1, t + tot + 1, a[i].st) - t;
 97         a[i].ed = lower_bound(t + 1, t + tot + 1, a[i].ed) - t;
 98         a[i].st *= 2, a[i].ed *= 2;
 99     }
100     tot *= 2;
101     seg_get_null(seg_null);
102     seg_build(seg_root = seg_null, 1, tot);
103     for (i = 1; i <= n; ++i)
104         seg_modify(seg_root, 1, tot, a[i].st, a[i].ed, i);
105     for (i = 1; i <= tot; ++i)
106         v[seg_query(seg_root, 1, tot, i)] = 1;
107     for (ans = 0, i = 1; i <= n; ++i)
108         ans += v[i];
109     printf("%d\n", ans);
110     return 0;
111 }

时间: 2024-11-06 03:48:39

BZOJ3888 [Usaco2015 Jan]Stampede的相关文章

线段树 BZOJ3888 [Usaco2015 Jan]Stampede

3888: [Usaco2015 Jan]Stampede Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 253  Solved: 81[Submit][Status][Discuss] Description Farmer John's N cows (1 <= N <= 50,000) appear to be stampeding along the road at the front of FJ's farm, but they are

[BZOJ 3888] [Usaco2015 Jan] Stampede 【线段树】

题目链接:BZOJ - 3888 题目分析 首先,计算出每个线段在 x 坐标 0 处出现的时间开始点和结束点,就转成了时间轴上的线段. 然后就是看每条线段是否被 y 比它小的线段完全覆盖了.注意求出的时间点要离散化,然后应该使用时间轴上的区间来表示,两线段端点重合并不是有共同部分. 将所有线段按照 y 从小到大排序之后,使用线段树判断它覆盖的区间是否已经都被前面的线段覆盖了. 然后将它所覆盖的区间覆盖. 就这样的一道题我WA了7次,还有救吗.. 代码 #include <iostream> #

BZOJ 3887[Usaco2015 Jan]Grass Cownoisseur

题面: 3887: [Usaco2015 Jan]Grass Cownoisseur Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 237  Solved: 130[Submit][Status][Discuss] Description In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow pat

bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们先考虑缩点.然后观察缩点后的图可以发现新的路径中必定只有一条边是反向的才符合条件.那么我们可以联想到某道最短路的题将边反向存一遍后分别从s和t跑一跑.那么这里bfs跑一跑就行了.然后有一个坑点:这种重建图的注意es和edges不然es会在中途就被修改掉了... #include<cstdio> #

3890: [Usaco2015 Jan]Meeting Time( dp )

简单的拓扑图dp.. A(i, j), B(i, j) 表示从点 i 长度为 j 的两种路径是否存在. 用bitset就行了 时间复杂度O(m) ---------------------------------------------------------------- #include<bits/stdc++.h> #define clr(x, c) memset(x, c, sizeof(x)) #define rep(i, n) for(int i = 0; i < n; ++

bzoj3886: [Usaco2015 Jan]Moovie Mooving

题意: PoPoQQQ要在电影院里呆L分钟,这段时间他要看小型电影度过.电影一共N部,每部都播放于若干段可能重叠的区间,PoPoQQQ决不会看同一部电影两次.现在问他要看最少几部电影才能度过这段时间? 注:必须看电影才能在电影院里呆着,同时一场电影可以在其播放区间内任意时间入场出场.N=20.每部电影的重复区间<=100. =>N=20.那么我们还是考虑二进制枚举.转移方程类似.时间复杂度类似.哎呀套路啊... #include<cstdio> #include<cstrin

【BZOJ3888】【Usaco2015 Jan】Stampede 线段树判区间覆盖

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44066313"); } 题意: PoPoQQQ站在原点上向y轴正半轴看,然后有一群羊驼从他眼前飞过.这些羊驼初始都在第二象限,尾巴在(Xi,Yi),头在(Xi+1,Yi),每Ci秒向右走一个单位. PoPoQQQ能看见一匹羊驼当且仅

【BZOJ3889】【Usaco2015 Jan】Cow Routing 双键值最短路

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44064091"); } 题意: 从样例讲起. 第一行 s,t,m表示:起点,终点,m条航线. 然后m组,每组第一行len,n表示这条航线的代价, 这类似于公交车,只要用了就花这些钱,但是用多少都这些钱. 注意是单向边. 举例: 23

【BZOJ3885】【Usaco2015 Jan】Cow Rectangles 某奇怪的最大子矩形

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44095063"); } 题意: 坐标系上给出n个点,分"H"和"G",一个整点坐标上至多一个点. 现在求一个不包含"G"的包含尽量多"H"的子矩形,然后