将数据离散化在使用线段树
有一面墙,被等分为1QW份,一份的宽度为一个单位宽度。现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW。后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报。现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报?(PS:看见一部分也算看到。)
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int nMax=10015;
int w[nMax<<3],add[nMax<<3];
int nl[nMax],nr[nMax];
int key[nMax<<1],ans;
bool is_p[nMax];
void build(int l,int r,int rt)
{
if(l==r)
{
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void update(int l,int r,int rt,int pl,int pr,int n)
{
if(pl<=l&&pr>=r)
{
w[rt]=n;
add[rt]=1;
return ;
}
int m=(l+r)>>1;
if(add[rt])
{
update(l,m,rt<<1,l,m,w[rt]);
update(m+1,r,rt<<1|1,m+1,r,w[rt]);
add[rt]=0;
}
if(pl<=m)
{
update(l,m,rt<<1,pl,pr,n);
}
if(pr>m)
{
update(m+1,r,rt<<1|1,pl,pr,n);
}
w[rt]=0;
}
void search(int l,int r,int rt)
{
if(w[rt])
{
if(!is_p[w[rt]])
{
ans++;
is_p[w[rt]]=true;
}
return ;
}
int m=(l+r)>>1;
search(l,m,rt<<1);
search(m+1,r,rt<<1|1);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int i,n,tot=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d",&nl[i],&nr[i]);
key[tot++]=nl[i];
key[tot++]=nr[i];
}
sort(key,key+tot);
tot=unique(key,key+tot)-key;
build(1,tot,1);
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)
{
int pl=lower_bound(key,key+tot,nl[i])-key+1;
int pr=lower_bound(key,key+tot,nr[i])-key+1;
update(1,tot,1,pl,pr,i);
}
memset(is_p,0,sizeof(is_p));
ans=0;
search(1,tot,1);
printf("%d\n",ans);
}
return 0;
}