BZOJ 3262 陌上花開 (三維偏序CDQ)
阿新 • • 發佈:2018-12-31
題目大意:
三維偏序裸題
首先,把三元組關於$a_{i}$排序
然後開始$CDQ$分治,回溯後按$b_{i}$排序
現在要處理左側對右側的影響了,顯然現在左側三元組的$a_{i}$都小於等於右側
而$c_{i}$這一維需要用權值樹狀陣列維護
歸併排序時,已知左側右側兩個指標分別是$i,j$
如果$b_{i} \leq bj$,將左側已經遍歷過的三元組的$c_{i}$推入樹狀陣列,然後$i++$
如果$b_{i}>bj$,那麼右側能取到的貢獻就是樹狀陣列內$\leq c_{j}$的三元組數量,然後$j++$
可三元組有重複的啊!
如果我們不去重,假設有兩個相同的三元組,靠前的三元組會得不到後面的貢獻
還需要去重,並額外記錄相同三元組數量
這道題的判定條件三個元是小於等於
發現我們只關於$a_{i}$排序也不行啊
在歸併過程中會發現有一些$b_{i}$或者是$c_{i}$明明比較大,卻得不到後面較小的貢獻
這是由於小於等於的情況也合法,而我們必須讓較大的在後面,才能保證後面能取到前面的貢獻
所以排序過程中第二維還要按$b_{i}$排序,第三維按$c_{i}$
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5#define N1 100100 6 #define ll long long 7 #define dd double 8 #define inf 0x3f3f3f3f3f3f3f3fll 9 using namespace std; 10 11 int gint() 12 { 13 int ret=0,fh=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 15 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 16 return ret*fh; 17 } 18 int n,nn,K; 19 struct node{ 20 int id,num,a,b,c; 21 friend bool operator == (const node &s1,const node &s2) 22 {return (s1.a==s2.a)&&(s1.b==s2.b)&&(s1.c==s2.c);} 23 friend bool operator < (const node &s1,const node &s2) 24 { 25 if(s1.a!=s2.a) return s1.a<s2.a; 26 if(s1.b!=s2.b) return s1.b<s2.b; 27 return s1.c<s2.c; 28 } 29 }p[N1],t[N1],tmp[N1]; 30 31 struct b_{i}T{ 32 int s[N1<<1]; 33 void update(int x,int w){for(int i=x;i<=K;i+=(i&(-i))) s[i]+=w;} 34 int query(int x){int ans=0; for(int i=x;i>0;i-=(i&(-i))) ans+=s[i]; return ans;} 35 }b; 36 int f[N1],hs[N1],que[N1],tl; 37 void CDQ(int L,int R) 38 { 39 if(R-L<=1) return; 40 int M=(L+R)>>1; 41 CDQ(L,M); CDQ(M,R); 42 int i=L,j=M,cnt=0; 43 while(i<M&&j<R) 44 { 45 if(t[i].b<=t[j].b){ 46 b.update(t[i].c,t[i].num); 47 tmp[++cnt]=t[i]; i++; que[++tl]=cnt; 48 }else{ 49 f[t[j].id]+=b.query(t[j].c); 50 tmp[++cnt]=t[j]; j++; 51 } 52 } 53 while(i<M){tmp[++cnt]=t[i]; i++;} 54 while(j<R){f[t[j].id]+=b.query(t[j].c); tmp[++cnt]=t[j]; j++;} 55 while(tl) i=que[tl--],b.update(tmp[i].c,-tmp[i].num); 56 for(i=L;i<R;i++) t[i]=tmp[i-L+1]; 57 } 58 59 int main() 60 { 61 scanf("%d%d",&n,&K); 62 int i; 63 for(i=1;i<=n;i++) p[i].a=gint(),p[i].b=gint(),p[i].c=gint(); 64 sort(p+1,p+n+1); 65 for(i=1;i<=n;i++) 66 if(!(p[i]==p[i-1])) t[++nn]=p[i],t[nn].num=1; 67 else t[nn].num++; 68 for(i=1;i<=nn;i++) t[i].id=i; 69 CDQ(1,nn+1); 70 for(i=1;i<=nn;i++) hs[f[t[i].id]+t[i].num-1]+=t[i].num; 71 for(i=0;i<n;i++) printf("%d\n",hs[i]); 72 return 0; 73 }