LG5308 [COCI2019] Quiz(wqs二分+斜率优化DP)
2021/9/25 23:13:05
本文主要是介绍LG5308 [COCI2019] Quiz(wqs二分+斜率优化DP),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
P5308 [COCI2019] Quiz
作为 wqs 二分的一道入门题,值得写一篇题解。
解题思路
首先我们考虑 \(O(n^2k)\) 的普通 DP。
我们令 \(f_{i,k}\) 为考虑淘汰 \(i\) 个人,分成 \(k\) 轮淘汰的最大收益。我们可以得到转移方程:
\[f_{i,k}=\max\limits_{j=0}^{i-1} f_{j,k-1}+\frac{i-j}{i} \]这个式子很难优化。二维的式子一般都很难进行优化。我们考虑化为一维状态,显然不太好化。
我们考虑先不管 \(k\) 的限制,那么我们有:
\[f_{i}=\max\limits_{j=0}^{i-1} f_{j}+\frac{i-j}{i} \]这样我们对这个式子进行 DP。(显然不考虑 \(k\) 后 \(f_i=\sum\limits_{i=1}^i \frac 1i\),但是我们先不管这个)
对于 \(k,j\) 两个转移点,若 \(j\) 优于 \(k\),我们有:
\[f_{j}+\frac{i-j}{i}>f_{k}+\frac{i-k}{i} \]\[\frac{f_j-f_k}{j-k}>\frac 1 i$$ 显然可以进行斜率优化了。时间复杂度为 $O(n)$ 我们在记录一个 $g_i$,记录 $f_i$ 这个状态分割了几段。显然,若最优转移点为 $j$,$g_i=g_j+1$。 现在考虑对于每次分割给予一些“奖赏”(“惩罚”也彳亍)。假设奖赏为 $x,x\in R$,则转移方程变成了: $$f_{i}=\max\limits_{j=0}^{i-1} f_{j}+\frac{i-j}{i}+x\]显然 \(x\) 越小分的段数越少。读者自证不难
而且这个方程还是可以斜率优化,式子和上面那个一样。但是此时我们可以通过控制 \(x\) 来控制分的段数。显然可以二分 \(x\)。每次检验 \(g_n\) 与 \(k\) 的关系即可。
二分出合适的 \(x\) 后把奖赏退回去即可。
时间复杂度 \(O(n\log N)\)。
代码实现
//Don't act like a loser. //This code is written by huayucaiji //You can only use the code for studying or finding mistakes //Or,you'll be punished by Sakyamuni!!! #include<bits/stdc++.h> #define lb long double using namespace std; int read() { char ch=getchar(); int f=1,x=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return f*x; } const int MAXN=1e5+10; const lb eps=1e-11; int n,m,h,t; int q[MAXN],g[MAXN]; lb f[MAXN]; lb k(int x,int y) { return (f[x]-f[y])/(x-y*1.0); } int dp(lb x) { h=t=1; q[1]=0; for(int i=1;i<=n;i++) { while(h<t&&k(q[h],q[h+1])>eps+1.00/i) { h++; } f[i]=f[q[h]]+(i*1.0-1.0*q[h])/(1.0*i)+x; g[i]=g[q[h]]+1; while(h<t&&k(q[t],q[t-1])+eps<k(q[t],i)) { t--; } q[++t]=i; } return g[n]>m; } signed main() { //freopen(".in","r",stdin); //freopen(".out","w",stdout); cin>>n>>m; lb l=-1e9,r=1e9,mid=0; for(int i=1;i<=150;i++) { mid=(l+r)/2; if(dp(mid)) { r=mid; } else { l=mid; } } dp((l+r)/2); cout<<fixed<<setprecision(9)<<f[n]-mid*m<<endl; //fclose(stdin); //fclose(stdout); return 0; }
这篇关于LG5308 [COCI2019] Quiz(wqs二分+斜率优化DP)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享