POJ 2528 Mayor's posters

来源:互联网 发布:mac加拿大官网 编辑:程序博客网 时间:2024/06/14 04:52

1.题目描述:点击打开链接

2.解题思路:本题要求给指定的区间覆盖上一种颜色,最后查询可以看到的颜色数量。可以考虑用线段树来模拟这一过程。这里考虑用左闭右开区间来描述,即[a,b+1)。同时,用0来表示此区间没有颜色覆盖或者是多种颜色覆盖的情况。不过由于区间的范围比较大,可以事先进行离散化处理。将区间端点取出后由小到大排序,然后把每个端点都映射为它排序后的下标。这样一来,只有n*2种不同的坐标,而且原来的覆盖关系保持不变。更新的时候,先pushdown上一次的颜色,然后再给本区间打上新的颜色。查询时候,如果本区间有颜色,或者已经到达叶子结点时候,标记该颜色后就直接返回。道理很显然,因为下面的颜色已经被覆盖了,无需再往下遍历了。这样,最后统计一下标记了多少个颜色即得到答案。

3.代码:

#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<complex>#include<functional>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define me(s)  memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, string> P;#define lid (id<<1)#define rid (id<<1|1)const int N = 20005;int vis[N];int n;struct Node{int l, r;int color;int mid() { return l + (r - l) / 2; }}tr[N*4];void build(int id, int L, int R){tr[id].l = L, tr[id].r = R;tr[id].color = 0;if (L +1 == R)return;int mid = tr[id].mid();build(lid, L, mid);build(rid, mid, R);}void pushdown(int id){if (tr[id].color){tr[lid].color = tr[id].color;tr[rid].color = tr[id].color;tr[id].color = 0;}}void update(int id, int L, int R, int val){int l = tr[id].l, r = tr[id].r;if (L <= l&&r <= R) { tr[id].color = val; return; }pushdown(id);int mid = tr[id].mid();if (L < mid)update(lid, L, R, val);//注意不要带等号,因为是左闭右开的区间if (R > mid)update(rid, L, R, val);}void query(int id, int L, int R){int l = tr[id].l, r = tr[id].r;if (tr[id].color || l + 1 == r) { vis[tr[id].color] = 1; return; }//如果当前区间有颜色,标记后就直接返回了query(lid, L, R);query(rid, L, R);}vector<int>y;map<int, int>H;int a[N], b[N];int main(){int T;scanf("%d", &T);while (T--){y.clear(); H.clear();scanf("%d", &n);for (int i = 0; i < n; i++){vis[i] = 0;scanf("%d%d", &a[i], &b[i]);b[i]++; //右端点变为开区间的端点y.push_back(a[i]);y.push_back(b[i]);}sort(y.begin(), y.end());y.erase(unique(y.begin(), y.end()), y.end());//离散化int len = y.size();for (int i = 0; i < len; i++)H[y[i]] = i;build(1, 0, len - 1);for (int i = 0; i < n; i++)update(1, H[a[i]], H[b[i]], i + 1);query(1, 1, len);int ans = 0;for (int i = 1; i <= n; i++)if (vis[i])ans++;printf("%d\n", ans);}}

0 0
原创粉丝点击