hdu 5618 Jam's problem again

Jam's problem again

 HDU - 5618 

题目大意:三维坐标,对于1个点,找出有多少个点,3个坐标都小于等于该点

/*
    这是一个三维偏序问题,三维分别是x,y,z
    第一维排序,第二维CDQ分治,第三维树状数组维护 
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100010
int t,n,sum[maxn];
struct node{
    int x,y,z,cnt,id;
    bool operator < (const node &p)const{
        if(x!=p.x)return x<p.x;
        if(y!=p.y)return y<p.y;
        if(z!=p.z)return z<p.z;
    }
    bool operator == (const node &p)const{
        return x==p.x&&y==p.y&&z==p.z;
    }
}q[maxn],tmp[maxn];
void add(int x,int c){
    while(x<maxn){
        sum[x]+=c;
        x+=x&(-x);
    }
}
int ask(int x){
    int res=0;
    while(x){
        res+=sum[x];
        x-=x&(-x);
    }
    return res;
}
void solve(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    solve(l,mid);solve(mid+1,r);
    for(int i=l,j=l,k=mid+1;i<=r;i++){
        if((q[j].y<=q[k].y||r<k)&&j<=mid)tmp[i]=q[j++],add(tmp[i].z,1);
        else tmp[i]=q[k++],tmp[i].cnt+=ask(tmp[i].z);
    }
    for(int i=l;i<=mid;i++)add(q[i].z,-1),q[i]=tmp[i];
    for(int i=mid+1;i<=r;i++)q[i]=tmp[i];
}
bool cmp(node a,node b){return a.id<b.id;}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
            q[i].id=i;q[i].cnt=0;
        }
        sort(q+1,q+n+1);
        for(int i=n-1;i>0;i--)
            if(q[i]==q[i+1])q[i].cnt=q[i+1].cnt+1;
        solve(1,n);
        sort(q+1,q+n+1,cmp);
        for(int i=1;i<=n;i++)printf("%d\n",q[i].cnt);
    }
    return 0;
}

 

posted @ 2017-12-21 19:51  Echo宝贝儿  阅读(167)  评论(0编辑  收藏  举报