CF739E Gosha is hunting(dp+凸优化)

暴力dp很简单,现在考虑优化,虽然本题可以选小于等于a,b,但是显然我们不会这么干,肯定用的越多越好

因此变成了选k个问题,这样就可以考虑使用wqs二分来优化,本质上就是我们二分一个附加权值给选择,原先我们是选的越多越优秀,现在的话就成为了一个单峰函数

我们观察这个函数取到极值点的时候选的个数是多少,如果大于所给条件,那么就增加权值,这样就能二分出答案直到刚好。最后算结果的时候把他加回来就好

CF739E Gosha is hunting(dp+凸优化)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
double eps=1e-8;
double f[N],fa[N],fb[N];
double p[N],q[N];
int n,a,b;
void cal(double w1,double w2){
    int i;
    for(i=1;i<=n;i++){
        f[i]=f[i-1];
        fa[i]=fa[i-1];
        fb[i]=fb[i-1];
        if(f[i]<f[i-1]+p[i]-w1){
            f[i]=f[i-1]+p[i]-w1;
            fa[i]=fa[i-1]+1;
            fb[i]=fb[i-1];
        }
        if(f[i]<f[i-1]+q[i]-w2){
            f[i]=f[i-1]+q[i]-w2;
            fa[i]=fa[i-1];
            fb[i]=fb[i-1]+1;
        }
        if(f[i]<f[i-1]+q[i]+p[i]-q[i]*p[i]-w2-w1){
            f[i]=f[i-1]+p[i]+q[i]-q[i]*p[i]-w2-w1;
            fa[i]=fa[i-1]+1;
            fb[i]=fb[i-1]+1;
        }
    }
}
int main(){
    //ios::sync_with_stdio(false);
    int i;
    cin>>n>>a>>b;
    for(i=1;i<=n;i++){
        cin>>p[i];
    }
    for(i=1;i<=n;i++){
        cin>>q[i];
    }
    double l1=0,r1=1;
    double l2,r2;
    while(l1+eps<=r1){
        double mid1=(l1+r1)/2;
        l2=0,r2=1;
        while(l2+eps<=r2){
            double mid2=(l2+r2)/2;
            cal(mid1,mid2);
            if(fb[n]>b)
                l2=mid2;
            else
                r2=mid2;
        }
        cal(mid1,r2);
        if(fa[n]>a){
            l1=mid1;
        }
        else{
            r1=mid1;
        }
    }
    cal(r1,r2);
    printf("%.6f\n",f[n]+a*r1+b*r2);
}
View Code

 

上一篇:【洛谷 2910】寻宝之路


下一篇:区间dp与滚动数组——[USACO10DEC]宝箱Treasure Chest