n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000) 。求出最后还能看见多少张海报。
Input
第一行: 样例个数T
第二行: 贴海报的人n
第三行: 每个人贴海报的范围
接下来n行: 每个人贴海报的范围
Output
对于每一个输入,输出最后可以看到的海报张数。下面这个图是样例解释
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
这个题如果你用普通的离散化,是错的
如三张海报为:1~10 1~4 6~10
离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。
新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)
X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10
这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3
最终,1~2为2,3为1,4~5为3,于是输出正确结果3。
for(int i=1;i<=n;i++){ scanf("%d%d",&li[i],&ri[i]); lsh[++cnt]=li[i]; lsh[++cnt]=ri[i]; } sort(lsh+1,lsh+cnt+1); int mm=unique(lsh+1,lsh+cnt+1)-(lsh+1); int nn=mm; for(int i=2;i<=nn;i++){ if(lsh[i]-lsh[i-1]>1){ lsh[++mm]=lsh[i-1]+1; } } sort(lsh+1,lsh+mm+1);
离散化之后就是线段树区间修改,和单点查询
建树修改+查询
build(1,1,mm); for(int i=1;i<=n;i++){ int x=lower_bound(lsh+1,lsh+mm+1,li[i])-lsh; int y=lower_bound(lsh+1,lsh+mm+1,ri[i])-lsh; update(1,x,y,i); } for(int i=1;i<=mm;i++){ int p=query(1,i); vis[p]++; } int ans=0; for(int i=1;i<=n;i++){ if(vis[i]){ ans++; } } cout<<ans<<endl;
#include<iostream> #include<algorithm> #include<cstring> using namespace std; /* 3 3 1 10 1 4 6 10 */ const int maxn=1e6+100; int lsh[maxn]; int li[maxn],ri[maxn]; int vis[maxn]; struct node{ int l,r; int lazy; }t[maxn]; int n; int cnt=0; void build(int p,int l,int r){ t[p].l=l; t[p].r=r; t[p].lazy=0; if(l==r){ t[p].lazy=0; return ; } int mid=(t[p].l+t[p].r)/2; build(p*2,l,mid); build(2*p+1,mid+1,r); } void upsh(int p){ t[2*p].lazy=t[p].lazy; t[2*p+1].lazy=t[p].lazy; t[p].lazy=0; } void update(int p,int l,int r,int x){ if(t[p].l>=l&&t[p].r<=r){ t[p].lazy=x; return ; } if(t[p].lazy){ upsh(p); } int mid=(t[p].l+t[p].r)/2; if(l<=mid){ update(2*p,l,r,x); } if(r>mid){ update(2*p+1,l,r,x); } } int query(int p,int x){ if(t[p].l==t[p].r){ return t[p].lazy; } if(t[p].lazy){ upsh(p); } int mid=(t[p].l+t[p].r)/2; if(x<=mid){ return query(2*p,x); } else{ return query(2*p+1,x); } } int main(){ int t; cin>>t; while(t--){ cin>>n; memset(vis,0,sizeof(vis)); cnt=0; for(int i=1;i<=n;i++){ scanf("%d%d",&li[i],&ri[i]); lsh[++cnt]=li[i]; lsh[++cnt]=ri[i]; } sort(lsh+1,lsh+cnt+1); int mm=unique(lsh+1,lsh+cnt+1)-(lsh+1); int nn=mm; for(int i=2;i<=nn;i++){ if(lsh[i]-lsh[i-1]>1){ lsh[++mm]=lsh[i-1]+1; } } sort(lsh+1,lsh+mm+1); build(1,1,mm); for(int i=1;i<=n;i++){ int x=lower_bound(lsh+1,lsh+mm+1,li[i])-lsh; int y=lower_bound(lsh+1,lsh+mm+1,ri[i])-lsh; update(1,x,y,i); } for(int i=1;i<=mm;i++){ int p=query(1,i); vis[p]++; } int ans=0; for(int i=1;i<=n;i++){ if(vis[i]){ ans++; } } cout<<ans<<endl; } }