题解:
CDQ分治
三重分治
第一重排序
第二重CDQ
第三重树状数组
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=100105; int n,m,c[N],dp[N],T; struct node { int x,y,z,id; }a[N],tmp[N]; struct Tree { int c[N]; inline int low(int x){return x&-x;} inline void modify(int x){while (x<=N-100)c[x]=0,x+=low(x);} inline void updata(int x){while (x<=N-100)c[x]++,x+=low(x);} inline void init(){memset(c,0,sizeof c);} inline int query(int x) { int ans=0; while (x)ans+=c[x],x-=low(x); return ans; } }Tree; inline int cmp(node x,node y) { if (x.x!=y.x)return x.x<y.x; if (x.y!=y.y)return x.y<y.y; return x.z<y.z; } inline int cmp1(node x,node y) { if (x.y!=y.y)return x.y<y.y; return x.z<y.z; } inline 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) { Tree.updata(tmp[pl].z); pl++; } dp[tmp[i].id]+=Tree.query(tmp[i].z); } for (int i=l;i<=m;i++)Tree.modify(tmp[i].z); solve(m+1,r); } inline int read() { int x=0;char c; for (;c<'0'||c>'9';c=getchar()); for (;c>='0'&&c<='9';c=getchar())x=x*10+c-48; return x; } inline void write(int x) { if (x>=10)write(x/10); putchar(x%10+48); } int main() { scanf("%d",&T); while (T--) { scanf("%d",&n); for (int i=1;i<=n;i++) { a[i].x=read(); a[i].y=read(); a[i].z=read(); a[i].id=i; } sort(a+1,a+n+1,cmp); memset(dp,0,sizeof dp); Tree.init(); solve(1,n); for (int i=n-1;i;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++)write(dp[i]),puts(""); } }