P3810 陌上花开 (CDQ分治)
CDQ分治付出了log的时间代价来使静态的三维偏序问题转化成了二位偏序问题后用用树状数组维护
所谓三位偏序就是a<=a1,b<=b1,c<=c1这种情况,我们将第一维当作时间轴,之后排序来树状数组
这道题是模板题
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int N=2e5+10; struct node{ int id; int a; int b; int c; int op; }q[N],q0[N]; int n,k; int tr[N]; int ans[N]; int lowbit(int x){ return x&-x; } void add(int x,int c){ int i; for(i=x;i<=k;i+=lowbit(i)){ tr[i]+=c; } } int sum(int x){ int res=0; int i; for(i=x;i;i-=lowbit(i)){ res+=tr[i]; } return res; } bool cmpa(node a,node b){ if(a.a==b.a) return a.op<b.op; return a.a<b.a; } bool cmpb(node a,node b){ if(a.b==b.b) return a.op<b.op; return a.b<b.b; } int cnt[N]; void cdq(int l,int r){ if(l==r) return ; int mid=l+r>>1; int i; cdq(l,mid); cdq(mid+1,r); sort(q+l,q+r+1,cmpb); for(i=l;i<=r;i++){ if(q[i].op==1&&q[i].a<=mid) add(q[i].c,1); if(q[i].op==2&&q[i].a>=mid+1) ans[q[i].id]+=sum(q[i].c); } for(i=l;i<=r;i++){ if(q[i].op==1&&q[i].a<=mid) add(q[i].c,-1); } for(i=l;i<=r;i++) q[i]=q0[i]; } int main(){ cin>>n>>k; int i; for(i=1;i<=n;i++){ scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c); q[i].op=1; q[i+n]=q[i]; q[i+n].id=i; q[i+n].op=2; } sort(q+1,q+1+2*n,cmpa); for(i=1;i<=2*n;i++) q[i].a=i; memcpy(q0,q,sizeof q); cdq(1,2*n); for(i=1;i<=n;i++){ --ans[i]; cnt[ans[i]]++; } for(i=0;i<n;i++){ printf("%d\n",cnt[i]); } }
没有人不辛苦,只有人不喊疼