POJ 2528 Mayor's posters (线段树+区间覆盖+离散化)

题意: 一共有n张海报, 按次序贴在墙上, 后贴的海报可以覆盖先贴的海报, 问一共有多少种海报出现过。

题解: 因为长度最大可以达到1e7, 但是最多只有2e4的区间个数,并且最后只是统计能看见的不同海报的数目,所以可以先对区间进行离散化再进行区间覆盖的操作。

由于墙上不贴东西的时候对后面没有影响, 所以可以不建树, 直接memset一下就好了。

因为是区域覆盖的问题, 树上原来的点并不会对后面的结果产生影响, 所以可以只修改lazy标记而不对树进行修改。

最后再用建树的操作访问一下lazy标记 并记录答案就好了。

代码


 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 #define lson l,m,rt<<1
 6 #define rson m+1,r,rt<<1|1
 7 #define fi first
 8 #define se second
 9 const int N = 20000+5;
10 int tree[N<<2], lazy[N<<2];
11 int a[N];
12 bool vis[N];
13 int ans, n, t;
14 pair<int,int> P[N];
15 
16 void Pushdown(int rt)
17 {
18     if(lazy[rt])
19     {
20         lazy[rt<<1|1] = lazy[rt<<1] = lazy[rt];
21         lazy[rt] = 0;
22     }
23 }
24 void Revise(int L, int R, int  C ,int l, int r, int rt)
25 {
26     if(L <= l && r <= R)
27     {
28         lazy[rt] = C;
29         return ;
30     }
31     Pushdown(rt);
32     int m = l+r >> 1;
33     if(L <= m) Revise(L,R,C,lson);
34     if(m < R)  Revise(L,R,C,rson);
35 }
36 void build(int l, int r, int rt)
37 {
38     if(lazy[rt])
39     {
40         if(!vis[lazy[rt]])
41         {
42             vis[lazy[rt]] = 1;
43             ans++;
44         }
45         return ;
46     }
48 int m = l+r >> 1; 49 build(lson); 50 build(rson); 51 } 52 int main() 53 { 54 ios::sync_with_stdio(false); 55 cin.tie(0); 56 cout.tie(0); 57 cin >> t; 58 while(t--) 59 { 60 ans = 0; 61 cin >> n; 62 for(int i = 1; i <= 2*n; i++) 63 { 64 cin >> a[i]; 65 P[i].fi = a[i], P[i].se = i; 66 } 67 sort(P+1,P+2*n+1); 68 int last = 0, cnt = 0; 69 for(int i = 1; i <= 2*n; i++) //离散化操作 70 { 71 if(P[i].fi == last) 72 a[P[i].se] = cnt; 73 else a[P[i].se] = ++cnt, last = P[i].fi; 74 } 75 memset(lazy, 0, sizeof(lazy)); 76 for(int i = 1; i <= 2*n; i+=2) 77 Revise(a[i],a[i+1],(i+1)/2,1,cnt,1);//由于每次的海报不同所以直接给海报一个编号 78 memset(vis, 0, sizeof(vis)); 79 build(1,cnt,1); 80 cout << ans << endl; 81 } 82 return 0; 83 }
posted @ 2018-01-30 16:44  Schenker  阅读(199)  评论(0编辑  收藏  举报