您的位置:首页 > 其它

POJ2528 线段树的区间操作

2014-03-24 21:19 267 查看
首先应该对该【0,10000000】进行离散化

即先将点集进行排序,然后从小到大缩小其中的间距,使得最后点数不会超过2*n

然后就是线段树操作

只需进行染色,然后最后用nlgn进行一个个查询颜色记录即可

#include<cstdio>

#include<cstring>

int color[20005*4],a[20005],p[20005],l[10005],r[10005],pd[10005],i,j,k,n,t,length;

void qs(int x,int y){

int i=x,j=y,k=a[(x+y)/2],t;

do{

while(a[i]<k) i++;

while(a[j]>k) j--;

if(i<=j){

t=a[i];a[i]=a[j];a[j]=t;

t=p[i];p[i]=p[j];p[j]=t;

i++;j--;

}

}while(i<j);

if(i<y) qs(i,y);

if(x<j) qs(x,j);

}

void build(int x,int y,int rt){

color[rt]=0;

if(x>=y) return;

int m=(x+y)/2;

build(x,m,2*rt);

build(m+1,y,2*rt+1);

}

void PushDown(int rt){

if(color[rt]!=0){

color[rt*2]=color[rt*2+1]=color[rt];

color[rt]=0;

}

}

void update(int x,int y,int rt){

if(l[k]<=x&&r[k]>=y){

color[rt]=k;

return;

}

PushDown(rt);

int m=(x+y)/2;

if(l[k]<=m) update(x,m,rt*2);

if(r[k]>m) update(m+1,y,rt*2+1);

}

int query(int x,int y,int rt){

if(color[rt]!=0){

if(!pd[color[rt]]) {

pd[color[rt]]=1;

return 1;

}

else return 0;

}

if(x==y) return 0;

int m=(x+y)/2;

return(query(x,m,rt*2)+query(m+1,y,rt*2+1));

}

int main()

{

scanf("%d",&t);

while(t--){

memset(pd,0,sizeof(pd));

scanf("%d",&n);

for(i=1;i<=n;i++){

scanf("%d%d",&a[2*i-1],&a[2*i]);

p[2*i-1]=2*i-1;

p[2*i]=2*i;

}

qs(1,2*n);

length=1;

for(i=1;i<=2*n;i++){

if(p[i]%2==0)

r[p[i]/2]=length;

else

l[(p[i]+1)/2]=length;

if(a[i]!=a[i+1]) length++;

}

build(1,length,1);

for(k=1;k<=n;k++)

update(1,length,1);

printf("%d\n",query(1,length,1));

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: