题意:在一面墙上贴海报,给出每张海报占的格子范围,求最后可以看到几张海报
思路:线段树,但是各自的范围是1~10000000。如果直接用线段树表示这么大范围肯定不够。但是海报最多就10000张,一个海报就两边。将出现过的边进行离散化,使需要的空间大大缩小
样例中的线段树大概长这个样子
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int C[80005];
int ans;
bool flag[10005];
int sl[10005];
int sr[10005];
int rec[20005];
int yl,yr;
int v;
void update(int o,int l,int r)
{
if(l==r){
C[o]=v;
return;
} else if(rec[l]>=yl&&rec[r]<=yr){
C[o]=v;
return;
} else {
int lc=o*2;
int rc=o*2+1;
int mid=l+(r-l)/2;
if(C[o]>=0){
C[lc]=C[o];
C[rc]=C[o];
C[o]=-1;
}
if(yl<=rec[mid])update(lc,l,mid);
if(yr>=rec[mid+1])update(rc,mid+1,r);
return;
}
}
void dfs(int o,int l,int r)
{
if(C[o]>0||l==r){
if(!flag[C[o]]){
flag[C[o]]=1;
ans++;
}
return;
} else if(C[o]==0){
return;
} else {
int mid=l+(r-l)/2;
dfs(o*2,l,mid);
dfs(o*2+1,mid+1,r);
}
}
int main()
{
// freopen("data.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int tot=0;
for(int i=0;i<n;++i){
scanf("%d%d",&sl[i],&sr[i]);
rec[tot++]=sl[i];
rec[tot++]=sr[i];
}
sort(rec,rec+tot);
tot=unique(rec,rec+tot)-rec;
memset(C,0,sizeof(C));
memset(flag,0,sizeof(flag));
for(int i=0;i<n;++i){
yl=sl[i];
yr=sr[i];
v=i+1;
update(1,0,tot-1);
}
ans=0;
dfs(1,0,tot-1);
printf("%d\n",ans);
}
return 0;
}