poj 2528 Mayor's posters (线段树+染色)
题目大意:
在一个长度为1e7单位的板子上贴海报,后贴上的会覆盖原来贴上的,问最后能看到几个海报(露出部分也可以)
思路
因为板子是1e7,但给出的海报个数为1e4,所以考虑离散化,普通的离散化是会漏掉颜色,比如 1 3 1 10 1 4 7 10,所以要在长度大于1区间之间在加一个点,记录这个区间的颜色。然后就是col本身即使树,也可以把他当lazy自身向下传递,最后查询时只需要查询有几种颜色,如果有颜色直接返回即可。
在updata时注意不要让叶子节点向下传递.....
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=4e4+10;
using namespace std;
struct node{
int l,r;
}e[maxn];
int arr[maxn],col[4*maxn],vis[maxn],n;
int ans=0;
void init(){
mem(col,0);
mem(vis,0);
mem(arr,0);
mem(e,0);
ans=0;
}
void updata(int l,int r,int left,int right,int c,int now)
{
int mid=(l+r)/2;
if(left<=l&&r<=right)
{
col[now]=c;
return ;
}
if(l>right) return ;
if(r<left) return ;
if(l==r) return ;//不要让叶子节点向下传递
if(col[now]!=0)
{
col[now*2]=col[now];
col[now*2+1]=col[now];
col[now]=0;
}
updata(l,mid,left,right,c,now*2);
updata(mid+1,r,left,right,c,now*2+1);
}
void query(int l,int r,int now)
{
int mid=(l+r)/2;
if(col[now]!=0)
{
if(!vis[col[now]])
{
ans++;
vis[col[now]]=1;
}
return ;
}
if(l==r) return ;
query(l,mid,now*2);
query(mid+1,r,now*2+1);
}
int main(){
int t;
scanf("%d",&t);
while(t--)
{
int tot=0,m=0;
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&e[i].l,&e[i].r);
arr[++tot]=e[i].l;
arr[++tot]=e[i].r;
}
sort(arr+1,arr+1+tot);
for(int i=1;i<=tot;i++)//去重
{
if(arr[i]!=arr[i-1])
arr[++m]=arr[i];
}
// for(int i=1;i<=m;i++)
// {
// cout<<arr[i]<<" ";
// }cout<<endl;
for(int i=m;i>1;i--)//加点
{
if(arr[i]-arr[i-1]!=1)
arr[++m]=arr[i-1]+1;
}
sort(arr+1,arr+1+m);
// for(int i=1;i<=m;i++)
// {
// cout<<arr[i]<<" ";
// }cout<<endl;
for(int i=1;i<=n;i++)
{
int l=lower_bound(arr+1,arr+1+m,e[i].l)-arr;
int r=lower_bound(arr+1,arr+1+m,e[i].r)-arr;
// cout<<l<<" "<<r<<endl;
updata(1,m+1,l,r,i,1);
}
query(1,m+1,1);
printf("%d\n",ans);
}
return 0;
}