BZOJ 3262: 陌上花开

经典CDQ分治题,求三维偏序

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=200000+200;

struct Node{

    int a,b,c;
    int num,level;
}node[maxn];

bool cmp(Node A,Node B){

    if(A.a==B.a&&A.b==B.b) return A.c<B.c;
    if(A.a==B.a) return A.b<B.b;
    return A.a<B.a; 
}

bool cmpcdq(Node A,Node B){

    if(A.b==B.b) return A.c<B.c;
    return A.b<B.b;
}

int tree[maxn],color[maxn];
int ans[maxn];
int type;
int n,k;
int tot;

inline int lowbit(int x){

    return x&(-x);
} 

void Add(int ind,int v){

    while(ind<=k){

        if(color[ind]!=type) tree[ind]=0;
        color[ind]=type;
        tree[ind]+=v;
        ind+=lowbit(ind);
    }
}

int getSum(int ind){

    int sum=0;
    while(ind>0){

        if(color[ind]==type) sum+=tree[ind];
        ind-=lowbit(ind);
    }
    return sum;
}


void CDQ(int l,int r){

    if(l==r) return ;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    CDQ(mid+1,r);
    sort(node+l,node+mid+1,cmpcdq);
    sort(node+mid+1,node+r+1,cmpcdq);
    int i=l;
    int j=mid+1;
    type++;
    for(;j<=r;j++){

        for(;node[i].b<=node[j].b&&i<=mid;i++) Add(node[i].c,node[i].num);
        node[j].level+=getSum(node[j].c); 
    }
}

int main(){

    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){

        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        node[i]=Node{a,b,c,1,0};
    }
    sort(node+1,node+n+1,cmp);
    tot=1;
    for(int i=2;i<=n;i++){

        if(node[i].a==node[tot].a&&node[i].b==node[tot].b&&node[i].c==node[tot].c) node[tot].num++;
        else node[++tot]=node[i];
    }
    CDQ(1,tot);
    for(int i=1;i<=tot;i++) ans[node[i].num+node[i].level-1]+=node[i].num;
    for(int i=0;i<n;i++) printf("%d\n",ans[i]);
} 

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81150360