题目链接:http://poj.org/problem?id=2528
(RE了不知道多少发,又接连WA了好几发..Debug了一下午...)
题意:
在墙上贴海报,每个人都可以贴一张海报,长度不限,海报之间可以相互覆盖,问最后能看到多少张海报(不一定是全部看见)。
这道题的数据范围很大,用线段树不可能把所有建立那么多节点,可以把区间当成点,离散化优化空间。
在区间离散化的时候不能用普通的离散方式,但是这道题数据比较水,即使是错误的离散方式也能够AC。
举例来说:
三个区间:[1,10] [1,4] [6,10]
普通的离散化得到的结果为x[1]=1,x[2]=4,x[3]=6,x[4]=10;
当进行染色时,[1,4],[1,2],[3,4]
这样的话最终[1,4]区间将会被完全覆盖,答案为2,实际答案应该为3.
解决的方式是if(x[i]-x[i-1]>1),那么在x[i]和x[i-1]之间添加一个点,这样就不会上述情况。
然后之后是线段树,注意数组的大小!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=20010; int T,n; int l[maxn],r[maxn],color[maxn<<4]; int x[maxn<<2],hash[maxn]; int ans; struct node{ int l; int r; int color; }node[maxn<<4]; void PushDown(int id);//从父节点向下更新 void build(int id,int l,int r);//建树 void Update(int id,int l,int r,int c);//区间更新,进行[l,r]区间染色 void Query(int id,int l,int r);//查询[l,r]区间内不同的颜色数 int binary_search(int low,int high,int a);//二分查找a所在位置 int main(){ #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif scanf("%d",&T); while(T--){ scanf("%d",&n); int p=0; for(int i=0;i<n;i++){ scanf("%d%d",&l[i],&r[i]); x[p++]=l[i],x[p++]=r[i]; } sort(x,x+p);//离散化 int cnt=1; for(int i=1;i<p;i++) if(x[i]!=x[i-1]) x[cnt++]=x[i]; for(int i=cnt-1;i>=1;i--) if(x[i]-x[i-1]>1) x[cnt++]=x[i-1]+1; sort(x,x+cnt); build(1,0,cnt); for(int i=0;i<n;i++){ int left=binary_search(0,cnt,l[i]); int right=binary_search(0,cnt,r[i]); Update(1,left,right,i); } ans=0; memset(hash,0,sizeof(hash)); Query(1,0,cnt); printf("%d\n",ans); } return 0; } void PushDown(int id){ node[id<<1].color=node[id<<1|1].color=node[id].color; node[id].color=-1; } void build(int id,int l,int r){ node[id].l=l; node[id].r=r; node[id].color=-1; if(l==r) return ; int mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); } void Update(int id,int l,int r,int c){ int L=node[id].l,R=node[id].r; if(l<=L&&R<=r){ node[id].color=c; return ; } if(node[id].color!=-1) PushDown(id); int mid=(L+R)>>1; if(l<=mid) Update(id<<1,l,r,c); if(r>mid) Update(id<<1|1,l,r,c); } void Query(int id,int l,int r){ if(node[id].color!=-1){ if(!hash[node[id].color]) ans++; hash[node[id].color]=1; return ; } if(l==r) return ; int mid=(l+r)>>1; Query(id<<1,l,mid); Query(id<<1|1,mid+1,r); } int binary_search(int low,int high,int a){ while(low<=high){ int mid=(low+high)>>1; if(x[mid]==a) return mid; else if(x[mid]>a) high=mid-1; else low=mid+1; } return -1; }