P3810 【模板】三维偏序(陌上花开) 题解(cdq分治模板)

题目链接

题目思路

cdq分治其实就是归并排序的思维

这个题目就是cdq套一个线段树就行

但是要注意有些点的坐标相同,要先去重,然后再写

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=5e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,m,k;
struct node{
    int x,y,z,cnt,ans;
}a[maxn],b[maxn],c[maxn];
int tree[maxn<<2];
int dp[maxn];
int pr[maxn];
ll ans=0;
void update(int node,int l,int r,int pos,int val){
    if(l==r){
        if(val==-1){
            tree[node]=0;
        }else{
            tree[node]+=val;
        }
        return ;
    }
    int mid=(l+r)/2;
    if(mid>=pos) update(node<<1,l,mid,pos,val);
    else update(node<<1|1,mid+1,r,pos,val);
    tree[node]=tree[node<<1]+tree[node<<1|1];
}
int query(int node,int L,int R,int l,int r){
    if(L<=l&&r<=R){
        return tree[node];
    }
    int mid=(l+r)/2,sum=0;
    if(mid>=L) sum+=query(node<<1,L,R,l,mid);
    if(mid<R)  sum+=query(node<<1|1,L,R,mid+1,r);
    return sum;
}

void cdq(int l,int r){
    if(l>=r){
        return ;
    }
    int mid=(l+r)/2;
    cdq(l,mid);
    cdq(mid+1,r);
    int pos1=l,pos2=mid+1,id=l;
    while(pos1<=mid&&pos2<=r){
        if(a[pos1].y<=a[pos2].y){
            update(1,1,k,a[pos1].z,a[pos1].cnt);
            b[id++]=a[pos1++];
        }else{
            a[pos2].ans+=query(1,1,a[pos2].z,1,k);
            b[id++]=a[pos2++];
        }
    }
    while(pos1<=mid) b[id++]=a[pos1++];
    while(pos2<=r)  a[pos2].ans+=query(1,1,a[pos2].z,1,k),b[id++]=a[pos2++];
    for(int i=l;i<=r;i++){
        update(1,1,k,b[i].z,-1);
        a[i]=b[i];
    }
}
bool cmp(node a,node b){
    if(a.x!=b.x){
        return a.x<b.x;
    }else if(a.y!=b.y){
        return a.y<b.y;
    }else{
        return a.z<b.z;
    }
}
signed main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    }
    sort(a+1,a+1+n,cmp);
    int sum=0;
    for(int i=1;i<=n;i++){
        sum++;
        if(a[i].x!=a[i+1].x||a[i].y!=a[i+1].y||a[i].z!=a[i+1].z){
            m++;
            c[m]=a[i];
            c[m].cnt=sum;
            sum=0;
        }
    }
    for(int i=1;i<=m;i++){
        a[i]=c[i];
        a[i].ans=0;
    }
    cdq(1,m);
    for(int i=1;i<=m;i++){
        int temp=a[i].cnt;
        while(temp--){
            pr[a[i].ans+a[i].cnt-1]++;
        }
    }
    for(int i=0;i<=n-1;i++){
        printf("%d\n",pr[i]);
    }
    return 0;
}


posted @ 2021-09-16 14:33  hunxuewangzi  阅读(26)  评论(0编辑  收藏  举报