模板题,cdq分治可以看http://blog.csdn.net/jaihk662/article/details/77720577
不过有两个地方不一样
①若干朵完全一样的花当成一朵再分治,因为属性一样算做互相超过
③若是x排序,y树状数组,z用cdq分治,一定要先将z离散化,因为它不是1-n的全排列
#include<stdio.h> #include<algorithm> using namespace std; int k, tre[200005]; typedef struct Res { int x, y, z, ans, sum; bool operator < (const Res &b) const { if(x<b.x || x==b.x && y<b.y || x==b.x && y==b.y && z<b.z) return 1; return 0; } }Res; Res s[200005], L[100005], R[100005]; int ans[200005]; bool comp(Res a, Res b) { if(a.z<b.z || a.z==b.z && a.y<b.y || a.z==b.z && a.y==b.y && a.x<b.x) return 1; return 0; } void Update(int x, int val) { while(x<=k) { tre[x] += val; x += x&-x; } } int Query(int x) { int ans = 0; while(x) { ans += tre[x]; x -= x&-x; } return ans; } void Cdq(int l, int r) { int i, p, q, m; if(l==r) return; m = (l+r)/2; for(i=l;i<=r;i++) { if(s[i].z<=m) Update(s[i].y, s[i].sum); else s[i].ans += Query(s[i].y); } for(i=l;i<=r;i++) { if(s[i].z<=m) Update(s[i].y, -s[i].sum); } p = q = 0; for(i=l;i<=r;i++) { if(s[i].z<=m) L[++p] = s[i]; else R[++q] = s[i]; } for(i=l;i<=m;i++) s[i] = L[i-(l-1)]; for(i=m+1;i<=r;i++) s[i] = R[i-m]; Cdq(l, m); Cdq(m+1, r); } int main(void) { int i, n, cnt; scanf("%d%d", &n, &k); for(i=1;i<=n;i++) { scanf("%d%d%d", &s[i].x, &s[i].y, &s[i].z); s[i].sum = 1; } sort(s+1, s+n+1); cnt = 0; for(i=1;i<=n;i++) { if(s[i].x==s[i-1].x && s[i].y==s[i-1].y && s[i].z==s[i-1].z) { s[cnt].sum++; continue; } s[++cnt] = s[i]; } sort(s+1, s+cnt+1, comp); for(i=1;i<=cnt;i++) s[i].z = i; sort(s+1, s+cnt+1); Cdq(1, cnt); for(i=1;i<=cnt;i++) { s[i].ans += s[i].sum-1; ans[s[i].ans] += s[i].sum; } for(i=0;i<=n-1;i++) printf("%d\n", ans[i]); return 0; }