题意:给出一个很大的范围(1 <= ri <= 10000000.)表示所给出的m次询问修改中会出现在这个范围中,问最后能够看到的完整海报数
思路:看到这么大的范围我们就会思考离散化数据,离散化说的高大上实际上就是压缩所给出的数据空间。因为所给出的数据不会布满(1至1e7)所以就把空白处的空间压成一个,其他连续的空间保留
注意的是,不连续的空间压缩时要增加空白空间作为间隙
完整代码:
#include <cstring> #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 1e5; const int inf = 0x3f3f3f3f; int seg[maxn<<2]; int lazy[maxn<<2]; int arr[maxn],ans[maxn]; int last; int L[maxn],R[maxn];//存储询问左右范围 int tot ; int Dseg[maxn];//压缩后的segment tree void push_up(int p){ if(seg[p<<1] == seg[p<<1|1]) seg[p] = seg[p<<1]; else seg[p] = inf; } void push_down(int p,int l,int r){ if(lazy[p]!= inf){ lazy[p<<1] = lazy[p]; lazy[p<<1|1] = lazy[p]; seg[p<<1] = lazy[p]; seg[p<<1|1] = lazy[p]; lazy[p] = inf; } } void build(int p,int l,int r){ if(l==r){ seg[p] = arr[l]; return ; } int mid = (l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); push_up(p); } void update(int p,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr){ seg[p] = v; lazy[p] = v; return ; } push_down(p,l,r); int mid = (l+r)>>1; if(ql <=mid) update(p<<1,l,mid,ql,qr,v); if(qr > mid) update(p<<1|1,mid+1,r,ql,qr,v); push_up(p); } void query(int p,int l,int r,int ql,int qr){ if(seg[p]!=inf){ if(seg[p]!= last) ans[seg[p]]++; last = seg[p]; return ; } if(l==r) {last = inf; return ;} int mid = (l+r)>>1; push_down(p,l,r); query(p<<1,l,mid,ql,qr); query(p<<1|1,mid+1,r,ql,qr); } int main(){ int n,T; cin>>T; while(T--){ tot = 0; cin>>n; if(!n) cout<<0<<endl; //由于每次都会有区间覆盖问题,所以这里相当于记录更新数据 else{ for(int k = 0;k<n;k++){ cin>>L[k]>>R[k]; Dseg[tot++] = L[k]; Dseg[tot++] = R[k]; } //离散处理 sort(Dseg,Dseg+tot); int len = unique(Dseg,Dseg+tot) - Dseg; int size = len; for(int i=1; i<size;i++){ //左右区间不连续,就增加空白区间(取比前一个空间大1) if(Dseg[i] - Dseg[i-1]>1) Dseg[len++] = Dseg[i-1]+1; } sort(Dseg,Dseg+len); for(int i = 0;i<n ; i++){ //再把离散好的重新存入L,R数组中 L[i] = lower_bound(Dseg,Dseg + len ,L[i]) - Dseg +1; R[i] = lower_bound(Dseg,Dseg + len ,R[i]) - Dseg +1; } memset(lazy,inf,sizeof(lazy)); memset(arr,inf,sizeof(arr)); memset(ans,0,sizeof(ans)); build(1,1,len); for(int i=0 ;i< n;i++){ update(1,1,len,L[i],R[i],i+1); } last = inf; //统计海报个数(也可以说是统计颜色) query(1,1,len,1,len); int cnt = 0; for(int i= 1;i <= len;i++){ if(ans[i]) cnt++; } cout<<cnt<<endl; } } }