POJ 2528 Mayor's posters [线段树]

来源:互联网 发布:扫一扫二维码软件下载 编辑:程序博客网 时间:2024/06/09 02:48

题意:有n张海报要贴在墙上,贴的范围是[L,R],问最后在墙上能看见几张海报。

题解:线段树的区间更新,我们用tree表示区间[L,R]是否只有一种海报,并且记录海报是哪个。每一次更新的时候,我们找到相应的区间设为海报的标号,并且加入海报标号。最后query的时候,只要询问每一个点上的颜色就可以了。

(注意:离散化的时候要加入一些新点,防止遗漏颜色,例如[1,5][1,2],[4,5]的更新,我们要加入3这个点保持答案的正确性)

AC代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define N 20005int b[N*2];int ql[N],qr[N];int tree[N*8],mark[N];void pushdown(int root){tree[root<<1]=tree[root<<1|1]=tree[root];tree[root]=0;}void update(int l,int r,int L,int R,int root,int x){if(l<=L&&R<=r){tree[root]=x;return ;}int mid=L+R>>1;if(tree[root])pushdown(root);if(r<=mid)update(l,r,L,mid,root<<1,x);else if(l>mid)update(l,r,mid+1,R,root<<1|1,x);else update(l,mid,L,mid,root<<1,x),update(mid+1,r,mid+1,R,root<<1|1,x);}int query(int L,int R,int root){if(L==R){if(tree[root]!=0&&!mark[tree[root]]){mark[tree[root]]=1;return 1;}return 0;}int mid=L+R>>1;if(tree[root])pushdown(root);return query(L,mid,root<<1)+query(mid+1,R,root<<1|1);}int main(){int T;scanf("%d",&T);while(T--){memset(tree,0,sizeof(tree));memset(mark,0,sizeof(mark));int n;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d%d",&ql[i],&qr[i]);b[i*4]=ql[i];b[i*4+1]=qr[i];b[i*4+2]=ql[i]+1;b[i*4+3]=qr[i]+1;}sort(b,b+4*n);int tot=unique(b,b+4*n)-b;for(int i=0;i<n;i++){int pos1=lower_bound(b,b+tot,ql[i])-b+1;int pos2=lower_bound(b,b+tot,qr[i])-b+1;update(pos1,pos2,1,tot-1,1,i+1);}printf("%d\n",query(1,tot-1,1));}}


原创粉丝点击