标签:
Description
Input
Output
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
题目大意:
大体是说有人要竞选需要投票什么的,不用理会,总之后面就是贴海报, 后面的能把前面的海报覆盖,海报每次贴不会到方格中间,
如果一个海报不是完全被贴上就算可以看到,问最后你能看到几张海报(英语渣,反正我是这么理解的)
输入
1 //T个样例 5 //下面5(n)张海报及其范围 1 <= n <= 10000 1 4 //海报的左右边界 1--10000000 2 6 8 10 3 4 7 10
输出
4 能看到4张海报
解题思路:
由于海报粘贴的方式,在外面的绝对不会被里面的遮住,所以倒着来覆盖海报比较方便
主要还是由于海报边界太大需要离散化,如果把海报的每个边界看成一个节点话最多需要的范围就成了20000 节点是80000
不过我不会离散化第一次看了课件,模仿着写的,不过听学长说貌似不算很好的离散化 或者完全不合格的离散化
我用的这种离散化还是要开一个100000000的一维数组 虽然开的下,这道题也能解决,不过学长说如果范围是几亿的话就没办法了
不过这道题还是能过的,新的离散化方法明天再搞吧
下面是代码
/*毕竟我是王宇浩*/ #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cstdlib> #include <cmath> #include <cctype> #define Max(a,b) ((a)>(b)?(a):(b)) #define ls rt<<1 #define rs rt<<1|1 using namespace std; const int N = 200010; int xx[N];//x[i]用来储存海报左右边,排列后节点的位置为i; int post[N * 50];//post[i]用来储存边i应该排列在第几个位置上面 struct Poster { int l, r; }P[N];//P[i]来储存第i张海报的左右边 struct node { int l, r; bool cover; int Mid() { return (l + r) >> 1; } }a[N<<2]; int cmp(const void *a, const void *b) { int *c, *d; c = (int *)a; d = (int *)b; return *c - *d; } void Build(int rt, int l, int r) { a[rt].l = l, a[rt].r = r, a[rt].cover = false; if(l == r) return ; Build(ls, l, a[rt].Mid()); Build(rs, a[rt].Mid()+1, r); } void UP(int rt) { //如果ls和rs都被覆盖, 则此区域被覆盖 if(a[rt].l == a[rt].r) return; if(a[ls].cover && a[rs].cover) a[rt].cover = true; } bool Search(int rt, int l, int r)//如果找到此区间未被覆盖,覆盖并返回true, 否则返回false; { bool ans; if(a[rt].cover) return false; if(a[rt].l == l && a[rt].r == r) { if(a[rt].cover) return false; else { a[rt].cover = true; return true; } } if(l > a[rt].Mid()) { ans = Search(rs, l, r); } else if(r <= a[rt].Mid()) { ans = Search(ls, l, r); } else { bool ans1 = Search(ls, l, a[rt].Mid()); bool ans2 = Search(rs, a[rt].Mid() + 1, r); ans = ans1 || ans2; } UP(rt);//每次放置海报之后就要向上更新 return ans; } int main() { int T, n; scanf("%d", &T); while (T--) { scanf("%d", &n); int index = 0; for(int i = 0; i < n; i++) { scanf("%d %d", &P[i].l, &P[i].r); xx[index++] = P[i].l; xx[index++] = P[i].r; } qsort(xx, index, sizeof(xx[0]), cmp);//对每个左右边的大小排序,确定其属于的节点位置 int index2 = 1; for(int i = 0; i < index; i++) {//每个边的位置确定一下,相同值为一个节点,相邻节点也相邻,不相邻节点之间空一个节点 post[xx[i]] = index2; if(i == index - 1) break;//判断到最后一个,结束循环,因为每次循环保存的都是下个节点的状态,及时结束防止数组越界 if(xx[i + 1] - xx[i] == 1) index2++; if(xx[i + 1] - xx[i] > 1) index2 += 2; } Build(1, 1, index2);//建立线段树 int ans = 0;//保存答案 for(int i = n - 1; i >= 0; i--) { if(Search(1, post[P[i].l], post[P[i].r])) ans++;//每次贴一张海报,判断会不会被覆盖,不会则答案+1 } printf("%d\n", ans); } } /* 1 5 1 4 2 6 8 10 3 4 7 10 */
标签:
原文地址:http://www.cnblogs.com/wangyuhao/p/4704297.html