线段树离散化+lazy标记
题意:
在墙上贴海报,海报可以相互覆盖,问最后可以看见几张海报
思路:
数据范围太大直接做超时超内存,需要离散化
举一组特殊样例
1-10 1-4 5-10
1-10 1-4 6-10
可以看出普通离散化的缺点
所以如果相邻数字间距大于1的话,则在其中加上一个数字
如
[1 2 4 6]
变为
[1 2 3 4 5 6]
代码如下#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 11111;
int N;
bool Hash[maxn];
int li[maxn],ri[maxn];
int X[maxn*4];
int col[maxn<<4];
int ans;
void Pushdown(int rt)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];
col[rt]=-1;
}
}
int bin(int x,int n)
{
int l,r,m;
l=0;r=n-1;
while(l<=r)
{
m=(l+r)>>1;
if(X[m]==x)return m;
else if(X[m]>x) r=m-1;
else l=m+1;
}
return -1;
}
void update(int L,int R,int x,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
col[rt]=x;
return;
}
Pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,x,l,m,rt<<1);
if(R>m) update(L,R,x,m+1,r,rt<<1|1);
}
void query(int l,int r,int rt)
{
if(col[rt]!=-1){
if(Hash[col[rt]]==false)ans++;
Hash[col[rt]]=true;
return ;
}
if(l==r)return ;
int m=(l+r)>>1;
query(l,m,rt<<1);
query(m+1,r,rt<<1|1);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
int m=0;
for(int i=0;i<N;i++)
{
scanf("%d%d",&li[i],&ri[i] );
X[m++]=li[i];
X[m++]=ri[i];
}
sort(X,X+m);
int cnt=1;
for(int i=1;i<m;i++)
{
if(X[i]!=X[i-1])X[cnt++]=X[i];
}
for(int i=cnt-1;i>0;i--)
{
if(X[i]!=X[i-1]+1)X[cnt++]=X[i-1]+1;
}
sort(X,X+cnt);
//for(int i=0;i<cnt;i++)cout<<X[i]<<" ";cout<<endl;
memset(col,-1,sizeof(col));
for(int i=0;i<N;i++)
{
int l=bin(li[i],cnt);
int r=bin(ri[i],cnt);
update(l,r,i,0,cnt,1);
}
memset(Hash,false,sizeof(Hash));
ans=0;
query(0,cnt,1);
printf("%d\n",ans);
}
return 0;
}