CDQ分治
第一层在外面排好序,第二层在分治时排序,第三层用树状数组维护
每层结束后清空树状数组
http://www.lydsy.com/JudgeOnline/problem.php?id=3262
/************************************************************** Problem: 3262 User: 1349367067 Language: C++ Result: Accepted Time:3280 ms Memory:7136 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 100011 #define K 200011 using namespace std; int n,k,tot=0,num=0; struct flo { int a,b,c,ans,s; flo() { ans=s=0; } }f[N],nf[N]; pair<int,int> tem[N]; bool cmp(flo a,flo b) { if (a.a==b.a&&a.b==b.b) return a.c<b.c; if (a.a==b.a) return a.b<b.b; return a.a<b.a; } int ans[N]={},U[N]={}; inline int lowbit(int x) {return x&(-x);} int sum(int x) { int res=0; while (x) {res+=U[x];x-=lowbit(x);} return res; } void update(int x,int a) { while (x<=k) {U[x]+=a;x+=lowbit(x);} } inline bool check(flo i,flo j) { if (i.a==j.a&&i.b==j.b&&i.c==j.c) return false; else return true; } bool cmp_(flo i,flo j) { if (i.b==j.b) return i.c<j.c; return i.b<j.b; } void solve(int l,int r) { if (l==r) return; int mid=(l+r)/2; solve(l,mid);solve(mid+1,r); sort(f+l,f+mid+1,cmp_); sort(f+mid+1,f+r+1,cmp_); int l1=l,l2=mid+1; while (l2<=r) { while (l1<=mid&&f[l1].b<=f[l2].b) { update(f[l1].c,f[l1].s); l1++; } f[l2].ans+=sum(f[l2].c); l2++; } for (int i=l;i<l1;i++) update(f[i].c,-f[i].s); return; } int fin[N]={}; void init() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d%d%d",&f[i].a,&f[i].b,&f[i].c); sort(f+1,f+n+1,cmp); for (int i=1;i<=n;i++) { if (check(f[i],f[i-1])) { num++; nf[num]=f[i]; nf[num].s=1; } else nf[num].s++; } for (int i=1;i<=num;i++) f[i]=nf[i]; solve(1,num); for (int i=1;i<=num;i++) fin[f[i].ans+f[i].s-1]+=f[i].s; for (int i=0;i<n;i++) printf("%d\n",fin[i]); } int main() { init(); //system("pause"); return 0; }