LG3810 【模板】三維偏序
阿新 • • 發佈:2021-12-20
本來就是很模板的題了,什麼時候把題解補上
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N=100005; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } struct node{int x,y,z,id,num,ans;}a[N],b[N]; inline bool cmpx(node x,node y){ if(x.x==y.x) return x.y==y.y?x.z<y.z:x.y<y.y; return x.x<y.x; } inline bool cmpy(node x,node y){ if(x.y==y.y) return x.z<y.z; return x.y<y.y; } int n,k,tot,bot[N],c[N]; inline int lowbit(int x){return x&-x;} inline void update(int i,int v){for(;i<=k;i+=lowbit(i))c[i]+=v;} inline int getsum(int i){int ans=0;for(;i;i-=lowbit(i))ans+=c[i];return ans;} void CDQ(int l,int r){//按橫座標排好序之後再進行分治就只需要考慮y,z的情況了 if(l==r)return; int mid=(l+r)>>1,i=l,j=mid+1; CDQ(l,mid);CDQ(mid+1,r); sort(a+l,a+mid+1,cmpy); sort(a+mid+1,a+r+1,cmpy); for(;j<=r;++j){//利用雙指標,滿足y的情況 while(a[i].y<=a[j].y&&i<=mid) update(a[i].z,a[i].num),++i; a[j].ans+=getsum(a[j].z);//利用樹狀陣列統計z滿足的數的數量 } for(int loc=l;loc<i;++loc)//只能清空對樹狀陣列有共享的位置 update(a[loc].z,-a[loc].num); }//只需要考慮分治左邊的數對右邊的數的共享,分治右邊的數自然也可以通過內部的分治來解決 int main(){ n=read(),k=read(); for(int i=1;i<=n;++i){ b[i].x=read(),b[i].y=read(),b[i].z=read(); }sort(b+1,b+1+n,cmpx); int tmp=0; for(int i=1;i<=n;++i){ ++tmp;//去重 if(b[i].x!=b[i+1].x||b[i].y!=b[i+1].y||b[i].z!=b[i+1].z) a[++tot]=b[i],a[tot].num=tmp,tmp=0; } /*for(int i=1;i<=tot;++i) printf("%d %d %d %d\n",a[i].x,a[i].y,a[i].z,a[i].num);*/ CDQ(1,tot); for(int i=1;i<=tot;++i) bot[a[i].ans+a[i].num-1]+=a[i].num;//相同的數可以認為滿足偏序 for(int i=0;i<n;++i)//顯然只能到n-1 printf("%d\n",bot[i]); return 0; }// 613ms / 5.27MB / 1.54KB C++14 O2