P3810 陌上花开(三维偏序,cdq分治模板)

mac2024-07-02  58

https://www.luogu.org/problem/P3810

 

//第一维排序,第二维cdq分治,第三维树状数组 #include<bits/stdc++.h> using namespace std; #define lowbit(x) (x&-(x)) const int maxn = 200006; int a[200009],ans[200009]; struct flower { int x,y,z,sum,cnt; bool operator==(const flower &p)const { return x==p.x&&y==p.y&&z==p.z; } } p[100009]; bool cmp1(flower a, flower b) { if(a.x != b.x) return a.x < b.x; if(a.y!=b.y) return a.y<b.y; return a.z < b.z; } bool cmp2(flower a, flower b) { return a.y < b.y; } void add(int x, int y) { for(int i = x; i<=maxn; i+=lowbit(i)) { a[i] += y; } } int sum(int x) { int ans = 0; for(int i = x; i; i-=lowbit(i)) { ans +=a[i]; } return ans; } void cdq(int l,int r) { if(l == r) return; int mid = ((l+r)>>1); cdq(l,mid); cdq(mid+1,r); //左半部分,右半部分的问题已解决 sort(p+l,p+mid+1,cmp2); sort(p+mid+1,p+r+1,cmp2); int i,j = l; //解决左半部分对右半部分的贡献(右半部分对左半部分无贡献) for(i = mid+1; i<= r; i++)//递归右半部分 { for(; j<=mid&&p[j].y<=p[i].y; j++)//左半部分x,y值小于右半部分的,树状数组记录 { add(p[j].z,p[j].cnt); } p[i].sum += sum(p[i].z); } for(i = l; i<j; i++)//把树状数组清空 { add(p[i].z,-p[i].cnt); } } int main() { int k,i,j,m,n; scanf("%d %d",&n, &m); for(i = 1; i <= n; i++) { scanf("%d %d %d",&p[i].x,&p[i].y,&p[i].z); p[i].sum = p[i].cnt = 0; } memset(a,0,sizeof(a)); sort(p+1,p+n+1,cmp1); k = 0; for(i = 1; i <= n; i++)//去重 { for(j = i; p[i]==p[j]&&j<=n; j++) { p[i].cnt ++;//记录这个元素的个数 } p[++k] = p[i]; i = j-1; } cdq(1,k); memset(ans,0,sizeof(ans)); for(i = 1; i<= k; i++) { ans[p[i].sum+p[i].cnt-1] += p[i].cnt; } for(i = 0; i< n; i++) { printf("%d\n",ans[i]); } return 0; }

 

最新回复(0)