[斜率优化] codefores 660F. Bear and Bowling 4

F. Bear and Bowling 4

题意:

给一个序列val,任选连续的一段[l,r],其价值为∑rj=lval[j]?(j?l+1),求最大价值 。

简单的说就是可以去掉这个序列的某前缀和某后缀,然后对新得到的val求ans=∑val[i]?i ,最后求max(ans)。

题解:

斜率优化,这个blog前面讲的不错。

花了两天才完全搞懂这个题。

怎么得出来的呢,我们一步一步来。

首先令sum[i]=∑ij=1val[j],令p[i]=∑ij=1val[j]?j。

然后我们就可以表示出任意[l,r]的答案,令为ans[l,r]=p[r]?p[l?1]?(l?1)?(sum[r]?sum[l?1])。

注意到里面l和l?1其实是一一对应的,为了方便,令ans[a,b]=p[b]?p[a]?a?(sum[b]?sum[a])。

这样可以得到一个O(n2)的暴力。

下面来优化。

设有任意三点k<j<i ,同时假设ans[j,i]>ans[k,i],把上面的ans代进去,我得到的结果如下:

(p[k]?k?sum[k])?(p[j]?j?sum[j])j?k>sum[i]

过程略,可以自行验证。

为了看起来简单,令y(x)=(p[x]?x?sum[x]),那么上面可以写成如下形式:

?y(j)?y(k)j?k>sum[i]

最初我推出的是这个式子,然而我用这个去维护却无法ac,后来我把左边完全化为斜率形式:

g(j,k)=y(j)?y(k)j?k<?sum[i]

显然g(j,k)可以看做j和k的斜率。

前面我们假设j>k并且ans[j,i]>ans[k,i]结果得到了这个式子。

结论就是,对于任意固定的i,如果有j>k且g(j,k)<?sum[i],便可以得出对于这个i,选择j要比选择k更好。

然而这样还没有得出如何优化,只得到了一个判断谁更优的方法。

同样假设k<j<i,如果满足g(i,j)<g(j,k),会发生什么情况呢?

如果g(i,j)<?sum[i],根据上面的结论,i点是优于j点的。

如果g(i,j)>?sum[i],那么有g(j,k)>g(i,j)>?sum[i],根据上面的结论,虽然j点优于i点,但是有k点优于j点。

结论就是,如果存在k<j<i且g(i,j)<g(j,k),那么j永远不会成为最优解,因为左边有k,右边有i。

所以我们去除所有这样的j点之后,也就是不存在g(i,j)<g(j,k)了。

本来对于一个i,为了求max(ans(l,i)),应该在i左边所有点里找到最优的l,现在去掉了不可能最优的点,这就是优化。

根据斜率来看,也就是任意三个点k<j<i,满足kj的斜率小于ji的斜率,整个曲线斜率递增,导数是为正的,形象一点可以想象f(x)=x2的曲线。

这种优化叫做斜率优化,它和几何斜率密切相关,膜一发CDQ女神。

现在对于一个i,已经知道了max(ans(l,i))中,l的解集,并且已经把不可能的点都从解集中去掉了,如何快速求出最优的l呢?

根据我们维护的斜率的单调性,有一种二分的方法。

假设l的解集为a1,a2,a3,…,an,对于任意k<j<i,根据前面的结论,如果满足g(aj,ak)<?sum[i],那么aj优于ak。

于是二分的时候,计算对于一个mid,是否满足g(amid,amid?1)<?sum[i]。

满足,说明amid优于amid?1,那么答案应该在mid的右边。

不满足,说明amid?1优于amid,那么答案应该在mid的左边。

二分的正确性在于我们已经维护好了g(ai,aj)单调递增。

容易发现我们是在解集里求一个极值点pos,满足g(apos,apos?1)<?sum[i]且g(apos,apos+1)<?sum[i]。

显然求极值同样可以采用三分法。

到这里,此题已经算是解决了,可喜可贺,收获颇丰。

附代码:

#include<stdio.h>
#include<algorithm>
using std::max;
typedef long long ll;
const int N = 2e5+5;
ll val[N], sum[N] = {0}, p[N] = {0};
int q[N], top, tail;
inline ll y(int x){ return p[x] - x*sum[x]; }
double g(int j, int k){
    double dy = y(j) - y(k);
    double dx = j - k;
    return dy/dx;
}
inline ll getans(int i, int j){
    return p[i] - p[j] - j*(sum[i] - sum[j]);
}
int solve(ll x){
    int l = top, r = tail-1, mid, res = l;
    while(l <= r){ //根据斜率二分求最优点
        mid = (l+r) >> 1;
        if(g(q[mid], q[mid-1]) < -x) l = mid+1, res = mid;
        else r = mid-1;
    }
    return q[res];
}
int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i){
        scanf("%lld", val+i);
        sum[i] = sum[i-1] + val[i];
        p[i] = p[i-1] + i*val[i];
    }
    top = tail = 0;
    q[tail++] = 0;
    ll ans = 0;
    for(int i = 1; i <= n; ++i){
        int j = solve(sum[i]); //对于固定的i,二分求最优点
        ans = max(ans, getans(i,j)); //更新答案
        while(top < tail-1 && g(i, q[tail-1]) < g(q[tail-1], q[tail-2])) tail--;  //满足了g(i,j)<g(j,k)
        q[tail++] = i;
    }
    printf("%lld\n", ans);
}
时间: 2024-08-29 20:54:04

[斜率优化] codefores 660F. Bear and Bowling 4的相关文章

【BZOJ3963】[WF2011]MachineWorks cdq分治+斜率优化

[BZOJ3963][WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先进的机械设备生产先进的机器.原来的那一台生产机器已经坏了,所以你要去为公司买一台新的生产机器.你的任务是在转型期内尽可能得到更大的收益.在这段时间内,你要买卖机器,并且当机器被ACM公司拥有的时候,操控这些机器以获取利润.因为空间的限制,ACM公司在任何时候都只能最多拥有一台机器. 在转型期内,有若

hdu3507 Print Article[斜率优化dp入门题]

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 11761    Accepted Submission(s): 3586 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

_bzoj1096 [ZJOI2007]仓库建设【斜率优化dp】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1096 又是一道经典斜率优化. #include <cstdio> const int maxn = 1000005; int n, c[maxn], head, tail, x[maxn]; long long sp[maxn], sxp[maxn], f[maxn]; char ch; struct point { long long x, y; int id; } que[maxn]

BZOJ - 1010【斜率优化DP】

1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9961  Solved: 4056[Submit][Status][Discuss] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过 压缩后变成一维长度为Ci.为了方便整理

斜率优化DP学习

转自:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html 我们知道,有些DP方程可以转化成DP[i]=f[j]+x[i]的形式,其中f[j]中保存了只与j相关的量.这样的DP方程我们可以用单调队列进行优化,从而使得O(n^2)的复杂度降到O(n). 可是并不是所有的方程都可以转化成上面的形式,举个例子:dp[i]=dp[j]+(x[i]-x[j])*(x[i]-x[j]).如果把右边的乘法化开的话,会得到x[i]*x[j

bzoj 1010 玩具装箱toy -斜率优化

P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的

BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]

1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9812  Solved: 3978[Submit][Status][Discuss] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P

bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路必须在同一天中走完. Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小. 帮助Pine求出最小方差是多少. 设方差是v,可以证明,v×m^2是一个整数.为了避免精度误差,输出结果时输出v×m^2. In

玩具装箱 bzoj1010 斜率优化

斜率优化的题好像都是这样的方程:左边关于j,k的一个(...)/(...)的式子,右边是个只与i有关的可算的数字: 然后把它放到二维坐标轴上,用单调队列维护一个凸壳,O(n)的复杂度: 这道题但是我发现我wrong了,找了程序看了一下,才发现斜率优化还有一点没理解:才明白上午T2能A是由于数据太水,出题人万岁! 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define LL long long