hdu 5618 Jam's problem again
Jam's problem again
题目大意:三维坐标,对于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; }