HDU 6183 Color it [KDtree+位压缩]

来源:互联网 发布:巫师3狼派装备数据 编辑:程序博客网 时间:2024/05/19 13:15
题意:在一个二维坐标系中,每次有两个操作:
①向一个点加入一种颜色。

②询问矩形区域[1,y1],[x,y2]范围内的不同颜色的数量。

题解:KDtree中64位sum记录每个节点的不用颜色的情况,或操作统计答案。

AC代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<vector>#define LL long longusing namespace std;const int mxn=350010;struct node{    int l,r;    int min[2],max[2];    int d[2];    LL w;    LL sum;}t[mxn];int root=0,nowD;int cmp(const node a,const node b){    return a.d[nowD]<b.d[nowD];}int cnt;int lim=0;inline void pushup(int rt,int x){    t[rt].max[0]=max(t[rt].max[0],t[x].max[0]);    t[rt].max[1]=max(t[rt].max[1],t[x].max[1]);    t[rt].min[0]=min(t[rt].min[0],t[x].min[0]);    t[rt].min[1]=min(t[rt].min[1],t[x].min[1]);    return;}inline bool in(int x1,int y1,int x2,int y2,int k){    return (x1<=t[k].min[0]&&t[k].max[0]<=x2&&y1<=t[k].min[1]&&t[k].max[1]<=y2);}inline bool out(int x1,int y1,int x2,int y2,int k){    return (x1>t[k].max[0]||x2<t[k].min[0]||y1>t[k].max[1]||y2<t[k].min[1]);}int Build(int l,int r,int D){    if(l>r)return 0;    nowD=D;int mid=(l+r)>>1;    nth_element(t+l,t+mid,t+r+1,cmp);///    t[mid].max[0]=t[mid].min[0]=t[mid].d[0];    t[mid].max[1]=t[mid].min[1]=t[mid].d[1];    t[mid].sum=t[mid].w;    //    t[mid].l=Build(l,mid-1,D^1);    if(t[mid].l)pushup(mid,t[mid].l);    t[mid].r=Build(mid+1,r,D^1);    if(t[mid].r)pushup(mid,t[mid].r);    //    t[mid].sum=t[mid].w|t[t[mid].l].sum|t[t[mid].r].sum;    return mid;}void insert(int &now,int x,int D){    if(!now){now=x;return;}    if(t[x].d[D]==t[now].d[D] && t[x].d[!D]==t[now].d[!D]){        t[now].w|=t[x].w;        t[now].sum|=t[x].w;        --cnt;        return;    }    if(t[x].d[D]<t[now].d[D]){        insert(t[now].l,x,D^1);        pushup(now,t[now].l);    }    else{        insert(t[now].r,x,D^1);        pushup(now,t[now].r);    }    t[now].sum=t[now].w|t[t[now].l].sum|t[t[now].r].sum;    return;}LL query(int rt,int x1,int y1,int x2,int y2){    if(!rt)return 0;    LL res=0;    if(in(x1,y1,x2,y2,rt)){return t[rt].sum;}    if(out(x1,y1,x2,y2,rt)){return 0;}    if(x1<=t[rt].d[0]&&t[rt].d[0]<=x2&&y1<=t[rt].d[1]&&t[rt].d[1]<=y2)res|=t[rt].w;    res|=query(t[rt].l,x1,y1,x2,y2)|query(t[rt].r,x1,y1,x2,y2);    return res;}int main(){    int i,j,op,x,y,w;    lim=9000;    LL lans=0;int X1,X2,Y1,Y2;    while(1){        scanf("%d",&op);        if(op==3)break;        if(op==1){cnt++;scanf("%d%d",&t[cnt].d[0],&t[cnt].d[1]);            LL ww;            scanf("%lld",&ww);            t[cnt].w=(1LL<<ww);t[cnt].sum=t[cnt].w;            t[cnt].max[0]=t[cnt].min[0]=t[cnt].d[0];            t[cnt].max[1]=t[cnt].min[1]=t[cnt].d[1];            insert(root,cnt,0);            if(cnt==lim){                lim+=9000;                root=Build(1,cnt,0);            }        }        else if(op==2){        X1=1;scanf("%d%d%d",&X2,&Y1,&Y2);            lans=query(root,X1,Y1,X2,Y2);            int ans=0;            for(LL i=0;i<51;i++)                if(lans&(1LL<<i))                    ans++;            printf("%d\n",ans);        }        else cnt=0,lim=9000,root=0,memset(t,0,sizeof(t));    }}


原创粉丝点击