POJ2528 线段树的区间操作

首先应该对该【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;
}

上一篇:Golang中map的三种声明方式和简单实现增删改查


下一篇:CodeForces 914DBash and a Tough Math Puzzle(线段树的骚操作)