Jam's problem again
Time Limit: 5000/2500 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
Jam喜欢坐标轴上的题,现在给出你一个三维的坐标轴,给出N个点,坐标分别为(x,y,z) 如果有两个点(xi,yi,zi)和(xj,yj,zj) 若xi≥xj yi≥yj zi≥zj 时 这个点的等级就加一,每个等级一开始为0 当然1≤x,y,z≤100000 1≤N≤100000 现在求每个点的等级
输入描述
第一行T(1≤T≤15),表示T组数据。 接下来T组数据: 第一行为N,表示点的数目 接下来N行,每一行三个整数x,y,z表示点的坐标
输出描述
输出N行,每行表示每个点的等级
输入样例
1 4 10 4 7 10 6 6 8 2 5 7 3 10
输出样例
1 1 0 0
Hint
第一个比第三个大,所以等级为1 第二个比第三个大,所以等级为1
分析:分治加树状数组
首先,我们可以对x按从小到大进行排序,分治的过程便是简单的cdq分治#include<bits/stdc++.h> using namespace std; const int maxn=100000+100; const int N=100010; struct node{ int id; int x,y,z; }a[maxn],tmp[maxn]; int dp[maxn],n; struct Bit{ int c[maxn]; void init(){ memset(c,0,sizeof(c)); } int lowbit(int x){ return x & -x; } void update(int x){ while(x<=N){ c[x]++; x+=lowbit(x); } } void modify(int x){ while(x<=N){ c[x]=0; x+=lowbit(x); } } int query(int x){ int ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; } }bit; bool cmp(node u,node v){ if(u.x!=v.x) return u.x<v.x; if(u.y!=v.y) return u.y<v.y; return u.z<v.z; } bool cmp1(node u,node v){ if(u.y!=v.y) return u.y<v.y; return u.z<v.z; } void solve(int l,int r){ if(l==r) return ; int m=(l+r)>>1; solve(l,m); for(int i=l;i<=r;i++) tmp[i]=a[i]; sort(tmp+l,tmp+m+1,cmp1); sort(tmp+m+1,tmp+r+1,cmp1); int pl=l; for(int i=m+1;i<=r;i++){ while(pl<=m&&tmp[pl].y<=tmp[i].y){ bit.update(tmp[pl].z); pl++; } dp[tmp[i].id]+=bit.query(tmp[i].z); } for(int i=l;i<=m;i++) bit.modify(tmp[i].z); solve(m+1,r); } int main(){ int _; scanf("%d",&_); while(_--){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); a[i].id=i; } sort(a+1,a+n+1,cmp); memset(dp,0,sizeof(dp)); bit.init(); solve(1,n); for(int i=n-1;i>=1;i--){ if(a[i].x==a[i+1].x&&(a[i].y==a[i+1].y)&&(a[i].z==a[i+1].z)) dp[a[i].id]=dp[a[i+1].id]; } for(int i=1;i<=n;i++) printf("%d\n",dp[i]); } return 0; }