题目
给定每张海报的覆盖区间,按顺序覆盖后,最后有几张海报没有被其他海报完全覆盖。
离散化处理完区间端点,排序后再给相差大于1的相邻端点之间再加一个点,再排序。
线段树,tree[i]表示节点i对应区间是哪张海报,如果是-1代表对应区间不是一张海报(0或多张)。
每贴一张海报,就用二分查找出覆盖的起点和终点对应的离散后的下标,然后更新区间。
线段树的区间更新可以加上懒惰标记(或延迟标记,但是这题可以不用另外标记。
#include<cstdio> #include<cstring> #include<algorithm> #define N 10005 using namespace std; int m,li[N],ri[N]; int x[N<<3],tree[N<<4],ans; bool hash[N]; void PushDown(int node){ tree[node<<1]=tree[node<<1|1]=tree[node]; tree[node]=-1; } void Update(int v,int l,int r,int node,int L,int R){ if(L>r||R<l)return; if(L<=l&&r<=R){ tree[node]=v; return; } if(tree[node]!=-1) PushDown(node); int m=l+r>>1; Update(v,l,m,node<<1,L,R); Update(v,m+1,r,node<<1|1,L,R); } void query(int l,int r,int node){ if(l==r){ if(tree[node]!=-1&&!hash[tree[node]]){ ans++; hash[tree[node]]=1; } return; } if(tree[node]!=-1)PushDown(node); int m=l+r>>1; query(l,m,node<<1); query(m+1,r,node<<1|1); } int main(){ freopen("in.txt","r",stdin); int t,n,i; scanf("%d",&t); while(t--){ memset(tree,-1,sizeof tree); memset(hash,0,sizeof hash); int k=0; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d%d",&li[i],&ri[i]); x[++k]=li[i]; x[++k]=ri[i]; } sort(x+1,x+k+1); m=1; for(i=2;i<=k;i++){ if(x[i]!=x[i-1])x[++m]=x[i]; } for(i=m;i>1;i--){ if(x[i]-x[i-1]>1)x[++m]=x[i]-1; } sort(x+1,x+m+1); for(i=1;i<=n;i++){ int l=lower_bound(x+1,x+m,li[i])-x; int r=lower_bound(x+1,x+m,ri[i])-x; Update(i,1,m,1,l,r); } ans=0; query(1,m,1); printf("%d\n",ans); } }
时间: 2024-11-13 12:23:50