Color it (CDQ segment tree or bits)

Original title: http://acm.hdu.edu.cn/showproblem.php?pid=6183

Meaning of the questions:

Multiple sets of cases in each group: given two operations:

  1. x    Y c x\; y\;c : at the point ( x , Y ) (X, y) put a color point c.
  2. x Y 1 Y 2 x\;y1\;y2 : inquiry ( 1 , Y 1 ) ( x , Y 2 ) (1,y1)\to(x,y2) this matrix the number of colors.

Resolution:

In fact, think of CDQ is better to do.

Partition process, update the right half of the query operation with the insertion of the left half. And past CDQ different, because the left half of the inserted color can and insert the query before the right half of the same color, it can not be applied directly.

My approach is this: on the left or right, respectively, X X sorting, along both sides of the traverse. Process, the left insertion segment tree maintenance, which is abit ortree line, the pressure to be like the presence or absence of color, position or query interval.

Each point will be accumulated to date maintained the position or in the calculation of the final answer, to avoid double counting.

note: I have been using __builtin_popcountto calculate Several, but not suited to long long, use__builtin_popcountll

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000009;
#define LL long long
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs ((rt<<1)|1)
int num=0;
struct node{
    int id;
    int f,x,y,c;
    bool operator<(const node &R)const{
        return x<R.x;
    }
}e[maxn];

LL sta[maxn];
int FF[maxn];
LL tr[maxn<<2];
void update(int rt,int l,int r,int p,LL val,int add){
    if(l==r){
        if(add)tr[rt]|=val;
        else tr[rt]=0;
        return;
    }
    if(p<=mid)update(ls,l,mid,p,val,add);
    else update(rs,mid+1,r,p,val,add);

    if(add)tr[rt]=tr[ls]|tr[rs];
    else tr[rt]=0;
}
LL query(int rt,int l,int r,int L,int R){
    if(l>=L&&r<=R){
        return tr[rt];
    }
    LL ans=0;
    if(L<=mid)ans|=query(ls,l,mid,L,R);
    if(R>mid)ans|=query(rs,mid+1,r,L,R);
    return ans;
}

void dfs(int l,int r){
    if(l==r)return;
    dfs(l,mid);dfs(mid+1,r);
    sort(e+l,e+1+mid);
    sort(e+mid+1,e+1+r);
    int ar1=l,ar2=mid+1;
    while(ar1<=mid&&ar2<=r){
        if(e[ar1].f==2){
            ar1++;continue;
        }
        if(e[ar2].f==1){
            ar2++;continue;
        }
        if(e[ar1].x<=e[ar2].x){
            update(1,1,1e6,e[ar1].y,1ll<<(e[ar1].c),1);
            ar1++;
            continue;
        }
        else{
            sta[e[ar2].id]|=query(1,1,1e6,e[ar2].y,e[ar2].c);
            ar2++;
            continue;
        }
    }
    while(ar2<=r){
        if(e[ar2].f==1){
            ar2++;continue;
        }
        sta[e[ar2].id]|=query(1,1,1e6,e[ar2].y,e[ar2].c);
        ar2++;
    }
    for(int i=l;i<=mid;i++){
        if(e[i].f==1)update(1,1,1e6,e[i].y,0,0);
    }
}

void deal(){
    if(num==0)return;
    memset(sta,0,sizeof sta);
    for(int i=1;i<=num;i++)FF[i]=e[i].f;
    dfs(1,num);
    for(int i=1;i<=num;i++){
        if(FF[i]==2){
            printf("%d\n",__builtin_popcountll(sta[i]));
        }
    }
}

int main(){
    int f;
    while(1){
        scanf("%d",&f);
        if(f==0||f==3){
            deal(),num=0;
            if(!f)continue;
            return 0;
        }
        e[++num].f=f;
        e[num].id=num;
        scanf("%d%d%d",&e[num].x,&e[num].y,&e[num].c);
    }
}

Guess you like

Origin blog.csdn.net/jk_chen_acmer/article/details/90721405