1. 程式人生 > >hdu 5618 Jam's problem again

hdu 5618 Jam's problem again

樹狀 ios ret scanf pro == stream blog targe

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; }

hdu 5618 Jam's problem again