1. 程式人生 > >BZOJ 2244 [SDOI2011]攔截導彈 (三維偏序CDQ+線段樹)

BZOJ 2244 [SDOI2011]攔截導彈 (三維偏序CDQ+線段樹)

題目大意:

洛谷傳送門

不愧為SDOI的duliu題

第一問?二元組的最長不上升子序列長度?裸的三維偏序問題,直接上$CDQ$

由於是不上升,需要查詢某一範圍的最大值,並不是字首最大值,建議用線段樹實現

第二問是個什麼玩意??

畫畫圖發現需要正反各做一次$CDQ$來統計

如果某個位置正反的答案$-1$就是最長長度

那麼它被選擇的次數就是 正著統計作為末尾的次數*反著統計作為末尾的次數

概率就是這個值/總次數

又發現某個位置作為末尾的次數可能非常非常大!

比如$1\;1\;2\;2\;3\;3\;4\;4\;5\;5....$這個值甚至達到了$2^{n/2}$

而題目又是讓我們求概率,所以這個次數必須要用$double$存

蒟蒻的程式碼寫得比較噁心..

另外聽一些神犇說$sort$中的$cmp$裡不能寫$<=$或$>=$,不然會$RE$

  1 #include <vector>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 50100
  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,m,mh,mv,K; 19 inline void chk(int &ma,dd &sum,int
w,dd num) 20 { 21 if(w>ma) ma=w,sum=num; 22 else if(w==ma) sum+=num; 23 } 24 25 struct SEG{ 26 int ma[N1<<2]; dd sum[N1<<2]; 27 void pushup(int rt) 28 { 29 ma[rt]=0; sum[rt]=0; 30 chk(ma[rt],sum[rt],ma[rt<<1],sum[rt<<1]); 31 chk(ma[rt],sum[rt],ma[rt<<1|1],sum[rt<<1|1]); 32 } 33 void update(int x,int l,int r,int rt,int w,dd num) 34 { 35 if(l==r) { chk(ma[rt],sum[rt],w,num); return; } 36 int mid=(l+r)>>1; 37 if(x<=mid) update(x,l,mid,rt<<1,w,num); 38 else update(x,mid+1,r,rt<<1|1,w,num); 39 pushup(rt); 40 } 41 void query(int L,int R,int l,int r,int rt,int &w,dd &num) 42 { 43 if(L<=l&&r<=R) { chk(w,num,ma[rt],sum[rt]); return; } 44 int mid=(l+r)>>1; 45 if(L<=mid) query(L,R,l,mid,rt<<1,w,num); 46 if(R>mid) query(L,R,mid+1,r,rt<<1|1,w,num); 47 } 48 void clr(int x,int l,int r,int rt) 49 { 50 ma[rt]=0; sum[rt]=0; 51 if(l==r) return; int mid=(l+r)>>1; 52 if(x<=mid) clr(x,l,mid,rt<<1); 53 else clr(x,mid+1,r,rt<<1|1); 54 } 55 }s; 56 struct node{int h,v,t,ans; dd sum;}a[N1],c[N1],tmp[N1]; 57 int h[N1],v[N1],que[N1],tl; 58 59 int cmp1(node s1,node s2){ if(s1.h!=s2.h) return s1.h>s2.h; return s1.v>=s2.v; } 60 int cmp2(node s1,node s2){ if(s1.h!=s2.h) return s1.h<s2.h; return s1.v<=s2.v; } 61 int cmpp(node s1,node s2){ if(s1.h!=s2.h) return s1.h>s2.h; return s1.v>s2.v; } 62 int cmpn(node s1,node s2){ if(s1.h!=s2.h) return s1.h<s2.h; return s1.v<s2.v; } 63 64 void CDQ1(int L,int R) 65 { 66 if(R-L<=1) return; 67 int M=(L+R)>>1,i,j,k,cnt; 68 for(i=L,j=M,k=L;k<R;k++) 69 { 70 if(a[k].t<M) tmp[i++]=a[k]; 71 else tmp[j++]=a[k]; 72 } 73 for(k=L;k<R;k++) a[k]=tmp[k]; 74 CDQ1(L,M); 75 for(i=L,j=M;i<M&&j<R;) 76 { 77 if(cmp1(a[i],a[j])) { s.update(a[i].v,1,mv,1,a[i].ans+1,a[i].sum); que[++tl]=i; i++; } 78 else { s.query(a[j].v,mv,1,mv,1,a[j].ans,a[j].sum); j++; } 79 } 80 while(j<R) { s.query(a[j].v,mv,1,mv,1,a[j].ans,a[j].sum); j++;} 81 while(tl) { s.clr(a[que[tl--]].v,1,mv,1); } 82 CDQ1(M,R); 83 for(i=L,j=M,cnt=0;i<M&&j<R;) 84 { 85 if(cmp1(a[i],a[j])) { tmp[++cnt]=a[i]; i++; } 86 else { tmp[++cnt]=a[j]; j++;} 87 } 88 while(i<M) tmp[++cnt]=a[i++]; 89 while(j<R) tmp[++cnt]=a[j++]; 90 for(k=L;k<R;k++) a[k]=tmp[k-L+1]; 91 } 92 void CDQ2(int L,int R) 93 { 94 if(R-L<=1) return; 95 int M=(L+R)>>1,i,j,k,cnt; 96 for(i=L,j=M,k=L;k<R;k++) 97 { 98 if(a[k].t<M) tmp[i++]=a[k]; 99 else tmp[j++]=a[k]; 100 } 101 for(k=L;k<R;k++) a[k]=tmp[k]; 102 CDQ2(L,M); 103 for(i=L,j=M;i<M&&j<R;) 104 { 105 if(cmp2(a[i],a[j])) { s.update(a[i].v,1,mv,1,a[i].ans+1,a[i].sum); que[++tl]=i; i++; } 106 else { s.query(1,a[j].v,1,mv,1,a[j].ans,a[j].sum); j++; } 107 } 108 while(j<R) { s.query(1,a[j].v,1,mv,1,a[j].ans,a[j].sum); j++;} 109 while(tl) { s.clr(a[que[tl--]].v,1,mv,1); } 110 CDQ2(M,R); 111 for(i=L,j=M,cnt=0;i<M&&j<R;) 112 { 113 if(cmp2(a[i],a[j])) { tmp[++cnt]=a[i]; i++; } 114 else { tmp[++cnt]=a[j]; j++;} 115 } 116 while(i<M) tmp[++cnt]=a[i++]; 117 while(j<R) tmp[++cnt]=a[j++]; 118 for(k=L;k<R;k++) a[k]=tmp[k-L+1]; 119 } 120 dd ret[N1]; 121 int p[N1]; 122 int de; 123 124 int main() 125 { 126 scanf("%d",&n); 127 int i,j,x,y,ans=0; dd sum=0; 128 for(i=1;i<=n;i++) { h[i]=a[i].h=gint(); v[i]=a[i].v=gint(); a[i].t=i; a[i].ans=1; a[i].sum=1; } 129 sort(h+1,h+n+1); mh=unique(h+1,h+n+1)-(h+1); sort(v+1,v+n+1); mv=unique(v+1,v+n+1)-(v+1); 130 for(i=1;i<=n;i++) { a[i].h=lower_bound(h+1,h+mh+1,a[i].h)-h; a[i].v=lower_bound(v+1,v+mv+1,a[i].v)-v;} 131 sort(a+1,a+n+1,cmpp); 132 CDQ1(1,n+1); 133 for(i=1;i<=n;i++) { c[i]=a[i]; p[a[i].t]=i; chk(ans,sum,a[i].ans,a[i].sum); } 134 sort(a+1,a+n+1,cmpn); for(i=1;i<=n;i++) { a[i].ans=1; a[i].sum=1; a[i].t=n-a[i].t+1; } 135 CDQ2(1,n+1); 136 for(i=1;i<=n;i++) 137 { 138 j=p[n-a[i].t+1]; 139 if(a[i].ans+c[j].ans-1<ans) ret[c[j].t]=0; 140 else ret[c[j].t]=1.0*c[j].sum*a[i].sum/sum; 141 } 142 printf("%d\n",ans); 143 for(i=1;i<=n;i++) printf("%.5lf ",ret[i]); 144 puts(""); return 0; 145 }