poj 2528 Mayor's posters

来源:互联网 发布:合肥腾锦网络 编辑:程序博客网 时间:2024/06/14 13:57

Problem:poj.org/problem?id=2528

参考:blog.csdn.net/non_cease/article/details/7383736

离散化要注意的一个细节上述参考博客讲得挺清楚的。

然而还有一个不太懂的问题(仿佛是个坑),就是有个数组不知道为什么要开那么大。

就是 tree[],是线段树的数组,N 个人,每人左、右边界两个值,最多的情况 2N 个值,然后线段树开 4 倍,

所以就 tree [ N * 2 * 4 ],即 tree [ N << 3 ],但会WA,改成 tree [ N << 4 ] 就可以;

其实还有一个是 pos[],离散化用的数组,因为最多的情况是 2N,所以开 pos [ N << 1 ],但会 RE,开 pos [ N << 2 ] 就可以,因为离散化的时候还要插多一些值进去(见参考博文),最多的情况应该是:原本没有重复(unique() 后没有减少)、离散化时每个数都要多插一个值,就变成 2N * 2,所以要开 pos [ N << 2 ]。

还有,update() 和 query() 的时候用左闭右开形式的区间错了好多次,后来换成闭区间的形式才过的。

Source Code

#include <cstdio>#include <cstring>#include <bitset>#include <algorithm>using namespace std;const int N = 10004;int tree[N<<4];// 线段树数组,记成段的颜色int l[N], r[N];// 每个人的左、右边界int pos[N<<2];// 用于边界的离散化bitset<N> bs;// 记录最后能显示的那些标号void pushdown(int x){if(~tree[x]){tree[x<<1] = tree[x<<1|1] = tree[x];tree[x] = -1;}}void update(int ul, int ur, int v, int l, int r, int id){if(ul <= l && r <= ur){tree[id] = v;return;}pushdown(id);int m = l + r >> 1;if(ul <= m)update(ul, ur, v, l, m, id<<1);if(ur > m)update(ul, ur, v, m+1, r, id<<1|1);}void query(int l, int r, int id){if(~tree[id]){bs[tree[id]] = 1;return;}if(l == r) return;int m = l + r >> 1;query(l, m, id<<1);query(m+1, r, id<<1|1);}int main(){int t;scanf("%d", &t);while(t--){int n, top = 0;scanf("%d", &n);for(int i=0; i<n; ++i){scanf("%d%d", l+i, r+i);pos[top++] = l[i];pos[top++] = r[i];}sort(pos, pos + top);top = unique(pos, pos + top) - pos;// 离散化坑点的解决:插值for(int i=top-1; i>0; --i)if(pos[i] != pos[i-1] + 1)pos[top++] = pos[i] - 1;sort(pos, pos + top);memset(tree, -1, sizeof tree);for(int i=0; i<n; ++i){int a = lower_bound(pos, pos + top, l[i]) - pos,b = lower_bound(pos, pos + top, r[i]) - pos;update(a, b, i, 0, top-1, 1);}bs.reset();query(0, top-1, 1);printf("%d\n", bs.count());}return 0;}


0 0