防不勝防:央視曝光 App 彈窗廣告三大陷阱
阿新 • • 發佈:2021-07-17
[模板] 三維偏序(陌上花開)
Solution:
CDQ分治求解三維偏序。
1、首先三關鍵字排序,保證接下來\(i\)的可行解一定在\([1,i-1]\)中。
2、再對第二關鍵字做歸併排序,保證滿足\(a_j<a_i\)的前提下,實現\(b_j<b_i\)。合併時有兩個區間,\(j<i\),\(j\)在\([l,mid]\)中,\(i\)在\([mid+1,r]\)中,由於前一次對三關鍵字的排序,使得左區間所有\(a\)小於等於右區間所有\(a\),所以在歸併維護答案時,無需顧忌\(a\)的情況,靠雙指標來保證\(b\)有序,然後同時統計\(c\)的答案即可。
3、歸併時雙指標與樹狀陣列維護第三關鍵字對答案的貢獻,注意重複三維點的情況。
Code:
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define dep(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; typedef unsigned long long ull; typedef long long ll; const int N=2e5+20; inline int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();} return x*f; } inline void out(int x) { if(x>9) out(x/10); putchar(x%10+'0'); } int n,k; struct node{ int a,b,c; int cnt; int sum; void print(){ cout<<"a="<<a<<" b="<<b<<" c="<<c<<" cnt="<<cnt<<" sum="<<sum<<endl; } bool operator < (const node &t)const{ if(t.a!=a)return a<t.a; if(t.b!=b)return b<t.b; return c<t.c; } bool operator == (const node &t)const{ return t.a==a&&t.b==b&&t.c==c; } node():a(0),b(0),c(0),cnt(0),sum(0){} node(int _a,int _b,int _c,int _cnt,int _sum):a(_a),b(_b),c(_c),cnt(_cnt),sum(_sum){} }q[N],w[N],kep[N]; int ans[N]; #define lowbit(x) (x&(-x)) int c[N]; void add(int pos,int val){ while(pos<N){ c[pos]+=val; pos+=lowbit(pos); } } int geta(int pos){ int ans=0; while(pos){ ans+=c[pos]; pos-=lowbit(pos); } return ans; } void merge_sort(int l,int r){ if(l==r)return ; int mid = (l+r)>>1; merge_sort(l,mid),merge_sort(mid+1,r); int i=l,j=mid+1; int k=0; while(i<=mid&&j<=r){ if(q[i].b<=q[j].b)add(q[i].c,q[i].cnt),w[k++]=q[i++]; else q[j].sum+=geta(q[j].c),w[k++]=q[j++]; } while(i<=mid)add(q[i].c,q[i].cnt),w[k++]=q[i++]; while(j<=r)q[j].sum+=geta(q[j].c),w[k++]=q[j++]; for(int o=l;o<=mid;++o)add(q[o].c,-q[o].cnt); for(int i=0,st=l;i<k;++i){ q[st+i] = w[i]; } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>k; rep(i,1,n){ int x,y,z; cin>>x>>y>>z; q[i]=node(x,y,z,1,0); } sort(q+1,q+1+n); int siz=0; for(int i=1;i<=n;++i){ int pos = i; int cnt = 0; while(pos<=n&&q[pos]==q[i]){ pos++; cnt++; } kep[++siz] = q[i]; kep[siz].cnt = cnt; i=pos-1; } for(int i=1;i<=siz;++i){ q[i] = kep[i]; } merge_sort(1,siz); for(int i=1;i<=siz;++i){ ans[q[i].cnt-1+q[i].sum]+=q[i].cnt; } for(int i=0;i<n;++i){ cout<<ans[i]<<"\n"; } return 0; }