bzoj千题计划145:bzoj3262: 陌上花开(三维偏序 CDQ分治)
http://www.lydsy.com/JudgeOnline/problem.php?id=3262
三维偏序
第一维排序,第二维CDQ分治,第三维树状数组
#include<cstdio> #include<iostream> #include<algorithm> #define lowbit(x) x&-x #define N 100001 #define M 200001 using namespace std; struct node { int a,b,c; int id; int cnt; }e[N],L[N],R[N]; int sum[N],ans[N]; int m; int c[M]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool cmp1(node p,node q) { if(p.a!=q.a) return p.a<q.a; if(p.b!=q.b) return p.b<q.b; return p.c<q.c; } bool cmp2(node p,node q) { return p.b<q.b; } void change(int x,int y) { while(x<=m) { c[x]+=y; x+=lowbit(x); } } int query(int x) { int sum=0; while(x) { sum+=c[x]; x-=lowbit(x); } return sum; } void solve(int l,int r) { if(l==r) { sum[e[l].id]+=e[l].cnt-1; return; } int mid=l+r>>1; for(int i=l;i<=mid;++i) L[i]=e[i]; for(int i=mid+1;i<=r;++i) R[i]=e[i]; sort(L+l,L+mid+1,cmp2); sort(R+mid+1,R+r+1,cmp2); int i=l,j=mid+1; for(;j<=r;++j) { while(i<=mid && L[i].b<=R[j].b) { change(L[i].c,L[i].cnt); i++; } sum[R[j].id]+=query(R[j].c); } for(int k=l;k<i;++k) change(L[k].c,-L[k].cnt); solve(l,mid); solve(mid+1,r); } int main() { int n; read(n); read(m); for(int i=1;i<=n;++i) { read(e[i].a); read(e[i].b); read(e[i].c); } sort(e+1,e+n+1,cmp1); for(int i=1;i<=n;++i) e[i].id=i; int tot=0; for(int i=1;i<=n;++i) { if(e[i].a!=e[i-1].a || e[i].b!=e[i-1].b || e[i].c!=e[i-1].c) { e[++tot].cnt=1; e[tot].a=e[i].a; e[tot].b=e[i].b; e[tot].c=e[i].c; e[tot].id=tot; } else e[tot].cnt++; } solve(1,tot); for(int i=1;i<=tot;++i) ans[sum[i]]+=e[i].cnt; for(int i=0;i<n;++i) cout<<ans[i]<<'\n'; }