poj 2528 Mayor’s posters 离散化+线段树

Posted 00isok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 2528 Mayor’s posters 离散化+线段树相关的知识,希望对你有一定的参考价值。

<题目链接>

题目大意:

往一堵墙上贴海报,依次输出这些海报张贴的范围,这些海报能够相互覆盖,问最后能够看见几张海报?

解题分析:

由于是给出每张海报的区间,所以在这些区间内的很多点可能用不上,所以我们采用离散化,将这个大的区间映射到一个更小更紧凑的区间。

但是只是这样简单的离散化是错误的, 如三张海报为:1~10 1~4 6~10 离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10 第一张海报时:墙的1~4被染为1; 第二张海报时:墙的1~2被染为2,3~4仍为1; 第三张海报时:墙的3~4被染为3,1~2仍为2。 最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。 新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的) X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10 这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3 最终,1~2为2,3为1,4~5为3,于是输出正确结果3。

 

这是我的WA代码:

 

技术分享图片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <set>
 5 
 6 using namespace std;
 7 typedef long long ll;
 8 const int M =2*10000+10;
 9 #define Lson rt<<1,l,mid
10 #define Rson rt<<1|1,mid+1,r
11 set<int>s;
12 struct Seg{
13     ll le,ri;
14 }seg[M<<4];
15 
16 ll tr[M<<4],lazy[M<<4],res[M<<4];
17 
18 void Pushdown(int rt,int len){
19     if(lazy[rt]){
20         lazy[rt<<1]=lazy[rt];
21         lazy[rt<<1|1]=lazy[rt];
22         tr[rt<<1]=tr[rt];
23         tr[rt<<1|1]=tr[rt];
24         lazy[rt]=0;
25     }
26 }
27 
28 void update(int rt,int l,int r,int L,int R,int c){
29     if(L<=l&&r<=R){
30         lazy[rt]=c,tr[rt]=c;
31         return;
32     }
33     Pushdown(rt,r-l+1);
34     int mid=(l+r)>>1;
35     if(L<=mid)update(Lson,L,R,c);
36     if(R>mid)update(Rson,L,R,c);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
37 
38 void query(int rt,int l,int r){
39     if(l==r){
40         s.insert(tr[rt]);
41         return;
42     }
43     Pushdown(rt,r-l+1);
44     int mid=(l+r)>>1;
45     query(Lson);
46     query(Rson);
47 }
48 
49 int main(){
50     int T;scanf("%d",&T);
51     while(T--){
52         int cnt=0;
53         s.clear();
54         int n;scanf("%d",&n);
55         memset(tr,0,sizeof(tr));
56         memset(lazy,0,sizeof(lazy));
57         for(int i=1;i<=n;i++){
58             scanf("%lld%lld",&seg[i].le,&seg[i].ri);
59             res[++cnt]=seg[i].le;
60             res[++cnt]=seg[i].ri;
61         }
62         sort(res+1,res+1+cnt);
63         int num=1; 
64         for(int i=2;i<=cnt;i++)
65             if(res[i]!=res[i-1])
66                 res[++num]=res[i];//去重
67         for(int i=num;i>=2;i--){
68             if(res[i]-res[i-1]>1)res[++num]=res[i]-1;
69         }
70         sort(res+1,res+1+num);
71         for(int i=1;i<=n;i++){
72             int left=lower_bound(res+1,res+1+num,seg[i].le)-res;
73             int right=lower_bound(res+1,res+1+num,seg[i].ri)-res;
74             update(1,1,num,left,right,i);
75         }
76         query(1,1,num);
77         printf("%d
",s.size());
78     }
79     return 0;
80 }
View Code

 

  

这是AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <set>
 5 using namespace std;
 6 
 7 #define Lson rt<<1,l,mid
 8 #define Rson rt<<1|1,mid+1,r
 9 const int maxn=10000+100;
10 int x[maxn<<4],tr[maxn<<4],lx[maxn<<2],rx[maxn<<2];
11 set<int>s;
12 
13 void Pushdown(int rt){
14     tr[rt<<1]=tr[rt<<1|1]=tr[rt];
15     tr[rt]=-1;
16 }
17 
18 void update(int rt,int l,int r,int L,int R,int c){
19     if(L<=l&&r<=R){
20         tr[rt]=c;
21         return;
22     }
23     if(tr[rt]!=-1)Pushdown(rt);  //如果tr[rt]==-1,说明不需要将该点的值Pushdown
24     int mid=(l+r)>>1;
25     if(L<=mid)update(Lson,L,R,c);
26     if(R>mid)update(Rson,L,R,c);
27 }
28 
29 void query(int rt,int l,int r){
30     if(tr[rt]!=-1){    //因为update的时候,只要该节点的区间包含在要求修改的区间内,就直接将值赋给该节点了,不会继续向下更新,所以,不用一直查询到子节点
31         s.insert(tr[rt]);    //用set来去掉重复的标号
32         return;
33     }
34     if(l==r)return;
35     if(tr[rt]!=-1)Pushdown(rt);
36     int mid=(l+r)>>1;
37     query(Lson);
38     query(Rson);
39 }
40 
41 int main(){
42     int T;scanf("%d",&T);
43     while(T--){
44         memset(tr,-1,sizeof(tr));
45         int cnt=0;
46         int n;scanf("%d",&n);
47         s.clear();
48         for(int i=1;i<=n;i++){
49             scanf("%d%d",&lx[i],&rx[i]);
50             x[++cnt]=lx[i];
51             x[++cnt]=rx[i];
52         }
53         sort(x+1,x+1+cnt);
54         int num=1;
55         for(int i=2;i<=cnt;i++){
56             if(x[i]!=x[i-1])x[++num]=x[i];  //去重
57         }
58         for(int i=num;i>=2;i--){
59             if(x[i]-x[i-1]>1)x[++num]=x[i]-1;  //如果两个点之间间距>1,那么在它们之间插入一个点
60         }
61         sort(x+1,x+1+num);
62         for(int i=1;i<=n;i++){
63             int le=lower_bound(x+1,x+1+num,lx[i])-x;    //找到该点离散化后的坐标
64             int ri=lower_bound(x+1,x+1+num,rx[i])-x;
65             update(1,1,num,le,ri,i);    //将这段区间染成 i
66         }
67         query(1,1,num);    //查找整个离散化后的区域总共有多少种标号
68         printf("%d
",s.size()); 
69     }
70     return 0;
71 }

 

 

2018-09-22

以上是关于poj 2528 Mayor’s posters 离散化+线段树的主要内容,如果未能解决你的问题,请参考以下文章

POJ-2528-Mayor's posters

poj2528 Mayor's posters 2011-12-20

[POJ2528]Mayor's posters

poj~2528 Mayor's posters

POJ2528 UVA10587 Mayor‘s posters线段树

POJ 2528-Mayor's posters-线段树+离散化