题目:http://poj.org/problem?id=2528
题意:给你一块很长的墙,不断的在墙上的一些区间贴广告,可以覆盖,问,最后可以看到的广告有几条。。。
分析:这题可以用扫描线+堆维护,也就是从左到右扫描,遇到广告的左端就把广告加到堆里面,保存的信息是第几次贴的广告,遇到右端就把广告从堆里面删掉就行,在删掉前,堆顶元素就是可见的,标记下。。。最后枚举求和
另一种做法就是线段树,因为坐标范围太大,需要离散化,也就是把普通线段树的坐标,换成数组里的值,也就是不连续的坐标,然后就是普通的线段树成段更新了,也是挺好写的,具体看代码吧
扫描线+堆维护 代码:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int mm=11111; struct node { int h,id; }g[mm<<1]; int p[mm],flag[mm],vis[mm],heap[mm]; int sz; void upsift(int k) { int i=k,j; while(i>1) { j=i>>1; if(heap[i]>heap[j]) { heap[0]=heap[i],heap[i]=heap[j],heap[j]=heap[0]; p[heap[i]]=i,p[heap[j]]=j; i=j; } else break; } } void downsift(int k) { int i=k,j; while(i*2<=sz) { j=i<<1; if(j<sz&&heap[j+1]>heap[j])++j; if(heap[i]<heap[j]) { heap[0]=heap[i],heap[i]=heap[j],heap[j]=heap[0]; p[heap[i]]=i,p[heap[j]]=j; i=j; } else break; } } bool cmp(node a,node b) { return a.h<b.h; } int main() { int i,j,l,r,n,m,t,ans; scanf("%d",&t); while(t--) { scanf("%d",&n); for(m=0,i=1;i<=n;++i) { scanf("%d%d",&l,&r); g[m].h=l,g[m].id=i,++m; g[m].h=r,g[m].id=i,++m; } sort(g,g+m,cmp); sz=i=0; memset(flag,0,sizeof(flag)); memset(vis,0,sizeof(vis)); while(i<m) { r=i+1; while(r<m&&g[r].h==g[i].h)++r; for(j=i;j<r;++j) { if(!flag[g[j].id]) { ++sz; heap[sz]=g[j].id; p[g[j].id]=sz; upsift(p[g[j].id]); downsift(p[g[j].id]); } ++flag[g[j].id]; } vis[heap[1]]=1; for(j=i;j<r;++j) if(flag[g[j].id]>1) { heap[p[g[j].id]]=l=heap[sz--]; p[l]=p[g[j].id]; upsift(p[l]); downsift(p[l]); flag[g[j].id]=0; } i=r; } for(ans=i=0;i<=n;++i)ans+=vis[i]; printf("%d\n",ans); } return 0; }
离散化+线段树 代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int mm=22222; int dly[mm<<2]; int l[mm],r[mm],a[mm],vis[mm]; void pushdown(int rt) { dly[rt<<1]=dly[rt<<1|1]=dly[rt]; dly[rt]=0; } void build() { memset(dly,0,sizeof(dly)); } void updata(int L,int R,int id,int l,int r,int rt) { if(L<=a[l]&&R>=a[r]) { dly[rt]=id; return; } if(dly[rt])pushdown(rt); int m=(l+r)>>1; if(a[m]>=L)updata(L,R,id,lson); if(m<r&&a[m+1]<=R)updata(L,R,id,rson); } void query(int rt) { if(dly[rt]) { vis[dly[rt]]=1; return; } query(rt<<1); query(rt<<1|1); } int main() { int i,j,t,n,m,ans; scanf("%d",&t); while(t--) { scanf("%d",&n); for(m=0,i=1;i<=n;++i) { scanf("%d%d",&l[i],&r[i]); a[m++]=l[i]; a[m++]=r[i]; } sort(a,a+m); for(j=i=0;i<m;++i) if(a[i]!=a[j])a[++j]=a[i]; m=j; build(); memset(vis,0,sizeof(vis)); for(i=1;i<=n;++i) updata(l[i],r[i],i,0,m,1); query(1); for(ans=i=0;i<=n;++i)ans+=vis[i]; printf("%d\n",ans); } return 0; }