题目连接:http://poj.org/problem?id=2528
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
分析:离散化+线段树,这题因为每个数字其实表示的是一个单位长度,因此离散化后的每个点如果相邻数字间距大于1的话,得在其中加上任意一个数字。
否则 如 [1 10] [1 3] [5 10]这组数据能看见3种海报,而离散化后[1,3,5,10]对应[1,2,3,4],更新[1,2]再更新[3,4]就能看见两种海报了。所以离散化应为[1,2,3,4,5,9,10].
#pragma comment(linker,"/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 1000000007 #define inf 0x3f3f3f3f #define N 200010 #define FILL(a,b) (memset(a,b,sizeof(a))) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; bool has[N]; int le[N],ri[N]; int col[N<<2],X[N]; int ans; int bin(int key,int n,int a[]) { int l=0,r=n-1; while(l<=r) { int m=(l+r)>>1; if(a[m]==key)return m; if(a[m]<key)l=m+1; else r=m-1; } } void Pushdown(int rt) { if(col[rt]!=-1) { col[rt<<1]=col[rt<<1|1]=col[rt]; col[rt]=-1; } } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { col[rt]=c; return; } Pushdown(rt); int m=(l+r)>>1; if(L<=m)update(L,R,c,lson); if(m<R)update(L,R,c,rson); } void query(int l,int r,int rt) { if(l==r) { if(col[rt]!=-1) { if(!has[col[rt]])ans++; has[col[rt]]=true; } return; } Pushdown(rt); int m=(l+r)>>1; query(lson); query(rson); } int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); int nn=0; for(int i=1;i<=n;i++) { scanf("%d%d",&le[i],&ri[i]); X[nn++]=le[i]; X[nn++]=ri[i]; } sort(X,X+nn); int m=1; for(int i=1;i<nn;i++) if(X[i]!=X[i-1])X[m++]=X[i]; for(int i=m-1;i>0;i--) if(X[i]!=X[i-1]+1)X[m++]=X[i-1]+1; sort(X,X+m); FILL(col,-1); for(int i=1;i<=n;i++) { int l=bin(le[i],m,X); int r=bin(ri[i],m,X); update(l+1,r+1,i,1,m,1); } ans=0;FILL(has,false); query(1,m,1); printf("%d ",ans); } }