[CDQ分治]三维偏序

题目链接

Code

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

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

const int maxn=100010;
inline int lowbit(int x){return x&(-x);}

struct BIT{
    int Node[300010];
    int N;
    void set_Len(int len){N=len;}
    void Update(int x,int Add){for(;x<=N;x+=lowbit(x)) Node[x]+=Add;}
    int PrefixSum(int x){int Res=0;for(;x;x-=lowbit(x)) Res+=Node[x];return Res;}
};
BIT Tree;

struct Point{int a,b,c;};
Point Data[maxn];
int ID[maxn],Count[maxn],temp[maxn],Cnt[maxn],Ans[maxn];
int N,K,top;

bool cmp(int x,int y){
    if(Data[x].a==Data[y].a){
        if(Data[x].b==Data[y].b) return Data[x].c<Data[y].c;
        return Data[x].b<Data[y].b;
    }
    return Data[x].a<Data[y].a;
}

void CDQ(int *id,int n){
    if(n==1) return;
    int mid=n>>1;
    CDQ(id,mid);
    CDQ(id+mid,n-mid);
    memcpy(temp+1,id+1,n*sizeof(int));
    RG k=1,i=1,j=mid+1;
    for(;i<=mid && j<=n;++k){
        int x=temp[i],y=temp[j];
        if(Data[x].b<=Data[y].b){Tree.Update(Data[id[k]=x].c,Count[x]);++i;}
        else{Cnt[y]+=Tree.PrefixSum(Data[id[k]=y].c);++j;}
    }
    --k;
    for(;j<=n;++j){
        Cnt[temp[j]]+=Tree.PrefixSum(Data[temp[j]].c);
        id[++k]=temp[j];
    }
    for(RG l=i-1;l>=1;--l)
        Tree.Update(Data[temp[l]].c,-Count[temp[l]]);
    for(;i<=mid;++i) id[++k]=temp[i];
    return;
}

void Unique(){
    sort(ID+1,ID+N+1,cmp);
    top=1;Count[ID[top]]=1;
    for(RG i=2;i<=N;++i){
        int x=ID[i],y=ID[top];
        if(Data[x].a^Data[y].a||Data[x].b^Data[y].b||Data[x].c^Data[y].c){
            ID[++top]=x;++Count[x];}
        else ++Count[ID[top]];
    }
    return;
}

int main(){
    Read(N);Read(K);
    Tree.set_Len(K);
    for(RG i=1;i<=N;++i){
        ID[i]=i;
        Read(Data[i].a);
        Read(Data[i].b);
        Read(Data[i].c);
    }
    Unique();
    CDQ(ID,top);
    for(RG i=1;i<=top;++i)
        Ans[Cnt[ID[i]]+Count[ID[i]]-1]+=Count[ID[i]];
    for(RG i=0;i<N;++i)
        printf("%d
",Ans[i]);
    
    return 0;
}
原文地址:https://www.cnblogs.com/AEMShana/p/12950410.html