三维偏序
首先把所有花按 x一序,y二序,z三序 排序,然后去重,con记录同样的花的个数,然后进行cdq
现在假设有[l.r]区间,其中[l,mid] [mid+1,r],已经递归处理完毕。我们把区间[l,mid] [mid+1,r]按 y一序,z二序,x三序 排序,那么现在所有[l,mid]区间里的x比所有[mid+1,r]区间里的x要小,并且在 [l,mid] [mid+1,r]中y是递增的。那么现在考虑[l,mid]中对[mid+1,r]中有贡献的个数,即只需要维护z的大小关系即可。对此用权值树状数组维护。
p.s. 在处理完区间之后对树状数组的清零操作不要用memset,直接update负值。这样能保证复杂度
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005,K=200005; 6 int n,k,tot,t[K],ans[N]; 7 struct qwe 8 { 9 int x,y,z,con,ans; 10 }a[N]; 11 bool cmp1(const qwe &a,const qwe &b) 12 { 13 return (a.x==b.x&&a.y==b.y&&a.z<b.z)||(a.x==b.x&&a.y<b.y)||(a.x<b.x); 14 } 15 bool cmp2(const qwe &a,const qwe &b) 16 { 17 return (a.y==b.y&&a.z==b.z&&a.x<b.x)||(a.y==b.y&&a.z<b.z)||(a.y<b.y); 18 } 19 int read() 20 { 21 int r=0,f=1; 22 char p=getchar(); 23 while(p>'9'||p<'0') 24 { 25 if(p=='-') 26 f=-1; 27 p=getchar(); 28 } 29 while(p>='0'&&p<='9') 30 { 31 r=r*10+p-48; 32 p=getchar(); 33 } 34 return r*f; 35 } 36 int lb(int x) 37 { 38 return x&(-x); 39 } 40 void update(int x,int v) 41 { 42 for(int i=x;i<=k;i+=lb(i)) 43 t[i]+=v; 44 } 45 int ques(int x) 46 { 47 int r=0; 48 for(int i=x;i>=1;i-=lb(i)) 49 r+=t[i]; 50 return r; 51 } 52 void cdq(int l,int r) 53 { 54 if(l==r) 55 { 56 a[l].ans+=a[l].con-1; 57 return; 58 } 59 int mid=(l+r)>>1; 60 cdq(l,mid); 61 cdq(mid+1,r); 62 sort(a+l,a+1+mid,cmp2); 63 sort(a+mid+1,a+1+r,cmp2); 64 int j=l; 65 for(int i=mid+1;i<=r;i++) 66 { 67 for(;j<=mid&&a[j].y<=a[i].y;j++) 68 update(a[j].z,a[j].con); 69 a[i].ans+=ques(a[i].z); 70 } 71 for(int i=l;i<j;i++) 72 update(a[i].z,-a[i].con); 73 } 74 int main() 75 { 76 n=read(),k=read(); 77 for(int i=1;i<=n;i++) 78 a[i].x=read(),a[i].y=read(),a[i].z=read(),a[i].ans=1; 79 sort(a+1,a+1+n,cmp1); 80 for(int i=1;i<=n;i++) 81 if(i!=1&&a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z) 82 a[tot].con++; 83 else 84 a[++tot]=a[i],a[tot].con++; 85 cdq(1,tot); 86 for(int i=1;i<=tot;i++) 87 ans[a[i].ans]+=a[i].con;//cout<<n<<endl; 88 for(int i=1;i<=n;i++) 89 printf("%d\n",ans[i]); 90 return 0; 91 }