三维偏序(cdq分治)

第一维对a排序

第二维归并排序,因为已经按a排过序,在左边和右边对b排序时仍保证左边的a小于右边

第三维树状数组,查询满足前两位偏序关系,且c小于当前数的个数

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
typedef long long ll;

const int maxn = 200010;

int n,k,cnt,ans=0;

struct Node{
    int a,b,c,v,id;
}a[maxn],b[maxn],lc[maxn],rc[maxn];

int s[maxn],f[maxn],d[maxn];

void add(int x,int v){ for(int i=x;i<=k;i+=i&(-i)) s[i]+=v; }
int sum(int x){ int res=0; for(int i=x;i>0;i-=i&(-i)) res+=s[i]; return res; }
void clear(int x){ for(int i=x;i<=k;i+=i&(-i)) s[i]=0; }

bool cmpx(Node a,Node b){ return a.a!=b.a?a.a<b.a:a.b!=b.b?a.b<b.b:a.c<b.c;  }
bool cmpy(Node a,Node b){ return a.b!=b.b?a.b<b.b:a.c<b.c; }

void cdq(int l,int r){
    if(l==r) return;
    int mid=(l+r)/2;
    cdq(l,mid),cdq(mid+1,r);
    
    for(int i=l;i<=mid;i++) lc[i]=b[i];
    for(int i=mid+1;i<=r;i++) rc[i]=b[i];

    sort(lc+l,lc+1+mid,cmpy);
    sort(rc+mid+1,rc+r+1,cmpy);

    int p=l,q=mid+1;
    
    while(p<=mid&&q<=r){
        if(lc[p].b<=rc[q].b){
            add(lc[p].c,lc[p].v);
            ++p;
        }
        else{
            f[rc[q].id]+=sum(rc[q].c);
            ++q;
        }
    }
    while(q<=r){
        f[rc[q].id]+=sum(rc[q].c);
        ++q;
    }

    for(int i=l;i<=mid;i++){
        clear(lc[i].c);
    }
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}

int main(){
    n=read(),k=read();
    for(int i=1;i<=n;i++){ a[i].a=read(),a[i].b=read(),a[i].c=read(),a[i].id=i; }
    sort(a+1,a+1+n,cmpx);
    
    for(int i=1;i<=n;i++){
        if(a[i].a==a[i-1].a&&a[i].b==a[i-1].b&&a[i].c==a[i-1].c){
            ++b[cnt].v;
        }else{
            b[++cnt].a=a[i].a,b[cnt].b=a[i].b,b[cnt].c=a[i].c,b[cnt].id=a[i].id;
            b[cnt].v=1;
        }
    }

    
    cdq(1,cnt);

    for(int i=1;i<=cnt;i++){
        d[f[b[i].id]+b[i].v-1]+=b[i].v;
    }
    for(int i=0;i<=n-1;i++){
        printf("%d\n",d[i]);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/10487258.html