题意:
给出一些区间,要按顺序将这些区间贴上海报,因此有些海报会被覆盖,求最终能看到多少种海报,只能看到一部分的也算。
解析:
因为一开始墙是空的,所以就不用build了,初始化sum数组都等于-1就好。因为没有求和求最大值之类的,只是求最后能显示在墙上的海报个数,所以也不用push_up,运用lazy-tag方法push_down往下更新就好,最后query对整体查询即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int t,m,n,a,b,c,q,k;
string s;
int sum[maxn << 2],z[maxn << 2],vis[maxn<<2],x[maxn],y[maxn],ans;
void push_down(int rt){
if(sum[rt] != -1){
sum[rt<<1] = sum[rt<<1|1] = sum[rt];
sum[rt] = -1;
}
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void update(int a,int b,int c,int l,int r,int rt){
if(a<=l && b>=r){
sum[rt] = c;
return;
}
push_down(rt);
int mid = (l+r)>>1;
if(a<=mid) update(a,b,c,lson);
if(b>mid) update(a,b,c,rson);
}
void query(int l,int r,int rt){
if(sum[rt] != -1){
if(!vis[sum[rt]]){
ans++;
}
vis[sum[rt]] = 1;
return ;
}
if(l==r) return;
int mid=(l+r) >> 1;
query(lson);
query(rson);
}
int bisearch(int num,int n){
int left = 0,right = n-1;
while(left<=right){
int mid = (left+right) >> 1;
if(z[mid] == num) return mid;
else if(z[mid]<num) left=mid+1;
else right=mid-1;
}
return -1;
}
int main(){
cin>>t;
while(t--){
memset(sum,-1,sizeof sum);
memset(vis,0,sizeof vis);
ans = 0;
scanf("%d",&n);
int pos = 0;
for(int i=0;i<n;i++){
scanf("%d%d",&x[i],&y[i]);
z[pos++] = x[i];
z[pos++] = y[i];
}
sort(z,z+pos);
int id = 1;
for(int i=1;i<pos;i++){
if(z[i] != z[i-1]){
z[id++]= z[i];
}
}
for(int i=id-1;i>0;i--){
if(z[i] != z[i-1] +1){
z[id++]=z[i-1]+1;
}
}
sort(z+1,z+id);
for(int i=0;i<n;i++){
int a=bisearch(x[i],id);
int b=bisearch(y[i],id);
update(a,b,i,0,id-1,1);
}
query(0,m-1,1);
printf("%d\n",ans);
}
return 0;
}