BZOJ 3262 陌上花开 (三维偏序CDQ+树状数组)
题目大意:
三维偏序裸题
首先,把三元组关于$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 }