LUOGU P3810 【模板】三维偏序(陌上花开)(CDQ分治)

传送门

 

解题思路

CDQ分治,和简单题的套路一样,一维排序,一维CDQ,一维树状数组,注意要把三者都相同的元素并到一起。数组不要开小了。。

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;
const int MAXQ = 100005<<2;
const int MAXN = 100005;
const int MAXK = 200005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}

int n,k,cnt,Num,f[MAXK];
int tot,ans[MAXN];

struct Query{
    int a,b,c;
    int num,val;
    bool friend operator<(const Query A,const Query B){
        if(A.a!=B.a) return A.a<B.a;
        if(A.b!=B.b) return A.b<B.b;
        return A.c<B.c;
    }
}q[MAXQ],tmp[MAXQ];

inline bool cmp(Query A,Query B){
    if(A.b!=B.b) return A.b<B.b;
    if(A.c!=B.c) return A.c<B.c;
    return A.a<B.a;
}

void add(int x,int y){
    for(;x<=k;x+=x&-x) f[x]+=y;
}

int query(int x){
    int ret=0;
    for(;x;x-=x&-x) ret+=f[x];
    return ret;
}

void Clear(int x){
    for(;x<=k;x+=x&-x) f[x]=0;
}

void cdq(int l,int r){
    if(l==r) return;
    int mid=l+r>>1;cdq(l,mid);cdq(mid+1,r);
    int L=l,R=mid+1,o=0;
    while(L<=mid && R<=r){
        if(q[L]<q[R]){
            add(q[L].c,q[L].num);
            tmp[++o]=q[L++];
        }
        else{
            q[R].val+=query(q[R].c);
            tmp[++o]=q[R++];
        }
    }
    while(L<=mid) tmp[++o]=q[L++];
    while(R<=r){    
        q[R].val+=query(q[R].c);
        tmp[++o]=q[R++];
    }
    for(register int i=l;i<=mid;i++) Clear(q[i].c);
    for(register int i=1;i<=o;i++) q[i+l-1]=tmp[i];
}

int main(){
    n=rd(),k=rd();
    for(int i=1;i<=n;i++)
        q[i].a=rd(),q[i].b=rd(),q[i].c=rd(),q[i].num=1;
    sort(q+1,q+1+n,cmp);cnt=1;
    for(int i=2;i<=n;i++){
        if(q[i].a==q[cnt].a && q[i].b==q[cnt].b && q[i].c==q[cnt].c)
            q[cnt].num++;
        else q[++cnt]=q[i];
    }
//    cout<<"    "<<endl;
//    for(int i=1;i<=cnt;i++)
//        cout<<q[i].a<<" "<<q[i].b<<" "<<q[i].c<<" "<<q[i].num<<endl; 
    cdq(1,cnt);
    for(int i=1;i<=cnt;i++) ans[q[i].val+q[i].num-1]+=q[i].num;
    for(int i=0;i<n;i++) printf("%d\n",ans[i]);
    return 0;
} 
View Code

 

posted @ 2018-09-24 20:49  Monster_Qi  阅读(213)  评论(0编辑  收藏  举报