[SDOI2011]拦截导弹
12分算法:
f[i]=max{f[j]}+1;(c[j]<c[i]&&a[j]<=a[i]&&b[j]<=b[i])(c代表时间)
g[i]代表以i为结尾的方案数,便有:g[i]=sigma{g[j]}(f[j]==f[i]-1)
但显然这样根本无法求出某一个在子序列中间的情况,
于是只可以n^2暴力更新第一问答案,期望得分12分。
40分算法:
用CDQ优化上面的DP,时间复杂度$ O(n*log2(n)) $,
于是便可以开心地拿到所有测试点第一问的分数。
85分算法:
我们设:
f1[i]代表以i为结尾的最大长度,g1[i]代表f1[i]的方案数,
f2[i]代表以i为开头的最大长度,g2[i]代表f2[i]的方案数。
之后便可以正反向跑一边CDQ,其实不用离散化,直接把树状数组的下标设为时间即可,但排序的时候一定要注意a,b一样的情况
树状数组在维护最大值的时候需要顺便维护最大值对应的方案数(原来树状数组可以这么干?!)
刚开始我用一个桶存储方案数概率一直超过1,问了cow mikufun之后才知道我的数组存的最大值中会有时间不满足题意的情况。
下面放上一段排序的代码(还有charm的)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
bool comp_a1(fire x,fire y) { if(x.a==y.a&&x.b==y.b) return x.c<y.c; if(x.a==y.a) return x.b>y.b; return x.a>y.a; } bool comp_b1(fire x,fire y) { if(x.b==y.b&&x.a==y.a) return x.c<y.c; if(x.b==y.b) return x.a>y.a; return x.b>y.b; } bool comp_b2(fire x,fire y) { if(x.b==y.b&&x.a==y.a) return x.c<y.c; if(x.b==y.b) return x.a<y.a; return x.b<y.b; } bool comp_a2(fire x,fire y) { if(x.a==y.a&&x.b==y.b) return x.c<y.c; if(x.a==y.a) return x.b<y.b; return x.a<y.a; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
inline bool operator <(BOOM a,BOOM b){return a.h>b.h;}
明显我的要复杂的多,但其实蛮好想的(主要不需要离散化),手玩一下样例就可以。
ans1=max{f1[i]};
设sum=sigma{g1[i]}(f1[i]==ans1)
于是每个导弹的概率便是:
g1[i]*g2[i]/sum (f1[i]+f2[i]-1==ans1)
0 (f1[i]+f2[i]-1!=ans1)
求解即可
100分算法:
方案数会爆long long所以用double或者__int128存储,
double类型会在数据非常大的时候舍弃一点精度来换取存储更大的数,
这个题精度1e-4就可以AC,所以double完全没问题。
void add(int x,int y,int z)
(啊啊啊函数调用double类型时时改成了long long爆了)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<string> 8 #include<cstring> 9 #include<map> 10 #define int long long 11 #define max(a,b) (a>b?a:b) 12 #define m(a) memset(a,0,sizeof(a)) 13 #define AA cout<<"Alita"<<endl 14 using namespace std; 15 const int N=5e4+10; 16 int ans,n,c[N]; 17 double ge,p[N],sum,a[N]; 18 struct fire{int a,b,c,w1,w2;double g1,g2;}f[N]; 19 int lowbit(int x){return x&-x;} 20 bool comp_a1(fire x,fire y) 21 { 22 if(x.a==y.a&&x.b==y.b) return x.c<y.c; 23 if(x.a==y.a) return x.b>y.b; 24 return x.a>y.a; 25 } 26 bool comp_b1(fire x,fire y) 27 { 28 if(x.b==y.b&&x.a==y.a) return x.c<y.c; 29 if(x.b==y.b) return x.a>y.a; 30 return x.b>y.b; 31 } 32 bool comp_b2(fire x,fire y) 33 { 34 if(x.b==y.b&&x.a==y.a) return x.c<y.c; 35 if(x.b==y.b) return x.a<y.a; 36 return x.b<y.b; 37 } 38 bool comp_a2(fire x,fire y) 39 { 40 if(x.a==y.a&&x.b==y.b) return x.c<y.c; 41 if(x.a==y.a) return x.b<y.b; 42 return x.a<y.a; 43 } 44 void add(int x,int y,double z) 45 { 46 while(x<=n) 47 { 48 if(c[x]<y) 49 { 50 c[x]=y; 51 a[x]=z; 52 } 53 else if(c[x]==y) 54 { 55 a[x]+=z; 56 } 57 x+=lowbit(x); 58 } 59 } 60 int get(int x) 61 { 62 int sum=0; 63 ge=0; 64 while(x) 65 { 66 if(c[x]>sum) 67 { 68 sum=c[x]; 69 ge=a[x]; 70 } 71 else if(c[x]==sum) 72 { 73 ge+=a[x]; 74 } 75 x-=lowbit(x); 76 } 77 return sum; 78 } 79 void clear(int x) 80 { 81 while(x<=n) 82 { 83 c[x]=0; 84 a[x]=0; 85 x+=lowbit(x); 86 } 87 } 88 void CDQ1(int l,int r) 89 { 90 if(l==r) return; 91 int mid=(l+r)>>1,x=l,y=mid+1; 92 CDQ1(l,mid); 93 stable_sort(f+l,f+mid+1,comp_b1); 94 stable_sort(f+mid+1,f+r+1,comp_b1); 95 while(x<=mid&&y<=r) 96 { 97 if(f[x].b>=f[y].b) 98 { 99 add(f[x].c,f[x].w1,f[x].g1); 100 x++; 101 } 102 else 103 { 104 int sum=get(f[y].c)+1; 105 if(f[y].w1<sum) 106 { 107 f[y].w1=sum; 108 f[y].g1=ge; 109 } 110 else if(f[y].w1==sum&&sum!=1) f[y].g1+=ge; 111 y++; 112 } 113 } 114 while(y<=r) 115 { 116 int sum=get(f[y].c)+1; 117 if(f[y].w1<sum) 118 { 119 f[y].w1=sum; 120 f[y].g1=ge; 121 } 122 else if(f[y].w1==sum&&sum!=1) f[y].g1+=ge; 123 y++; 124 } 125 for(int i=l;i<x;i++) 126 { 127 clear(f[i].c); 128 } 129 stable_sort(f+mid+1,f+r+1,comp_a1); 130 CDQ1(mid+1,r); 131 } 132 void CDQ2(int l,int r) 133 { 134 if(l==r) return; 135 int mid=(l+r)>>1,x=l,y=mid+1; 136 CDQ2(l,mid); 137 stable_sort(f+l,f+mid+1,comp_b2); 138 stable_sort(f+mid+1,f+r+1,comp_b2); 139 while(x<=mid&&y<=r) 140 { 141 if(f[x].b<=f[y].b) 142 { 143 add(f[x].c,f[x].w2,f[x].g2); 144 x++; 145 } 146 else 147 { 148 int sum=get(f[y].c)+1; 149 if(f[y].w2<sum) 150 { 151 f[y].w2=sum; 152 f[y].g2=ge; 153 } 154 else if(f[y].w2==sum&&sum!=1) 155 { 156 f[y].g2+=ge; 157 } 158 y++; 159 } 160 } 161 while(y<=r) 162 { 163 int sum=get(f[y].c)+1; 164 if(f[y].w2<sum) 165 { 166 f[y].w2=sum; 167 f[y].g2=ge; 168 } 169 else if(f[y].w2==sum&&sum!=1) 170 { 171 f[y].g2+=ge; 172 } 173 y++; 174 } 175 for(int i=l;i<x;i++) 176 { 177 clear(f[i].c); 178 } 179 stable_sort(f+mid+1,f+r+1,comp_a2); 180 CDQ2(mid+1,r); 181 } 182 signed main() 183 { 184 //freopen("1.in","r",stdin); 185 //freopen("1.out","w",stdout); 186 scanf("%lld",&n); 187 for(int i=1;i<=n;i++) 188 { 189 f[i].c=i; 190 scanf("%lld%lld",&f[i].a,&f[i].b); 191 f[i].w1=1; f[i].w2=1; 192 f[i].g1=1; f[i].g2=1; 193 } 194 stable_sort(f+1,f+n+1,comp_a1); 195 CDQ1(1,n); 196 for(int i=1;i<=n;i++) ans=max(ans,f[i].w1); 197 for(int i=1;i<=n;i++) 198 { 199 if(f[i].w1==ans) sum+=f[i].g1; 200 } 201 for(int i=1;i<=n;i++) f[i].c=n-f[i].c+1; 202 stable_sort(f+1,f+n+1,comp_a2); 203 CDQ2(1,n); 204 for(int i=1;i<=n;i++) 205 { 206 if(sum==0) continue; 207 f[i].c=n-f[i].c+1; 208 if(f[i].w1+f[i].w2-1==ans) p[f[i].c]=f[i].g1*f[i].g2/sum; 209 } 210 printf("%lld\n",ans); 211 for(int i=1;i<=n;i++) printf("%0.6lf ",p[i]); 212 return 0; 213 }