【JZOJ4249】游戏【贪心】

题目大意:

题目链接:https://jzoj.net/senior/#main/show/4249
一个长度为 n n n的数列,每次可以选择前面任意一个位置 i i i跳到那里,价值为 a i × ( i − a_i\times(i- ai×(i你所在的位置 ) ) )。求跳到 n n n的最大价值。


思路:

证明:每次选择 m a x { a i ( i ∈ j ∼ n ) } max\{a_i(i\in j\sim n)\} max{ai(ijn)} 其中 j j j 表示你所在的位置。

先设起点是0。
那么假设 i i i是最大价值的点,但是最优解应该先跳到 j j j,且下一次将跳到 k k k,且 j &lt; i &lt; k j&lt;i&lt;k j<i<k
那么从0跳到 j j j的价值是 j × a j j\times a_j j×aj,跳到 i i i的价值是 i × a i i\times a_i i×ai
j j j跳到 k k k的价值是 ( k − j ) a k (k-j)a_k (kj)ak,从 i i i跳到 k k k的价值是 ( k − i ) a k (k-i)a_k (ki)ak
明显从 j j j跳到 k k k的价值比从 i i i跳到 k k k的价值大 ( i − j ) a k (i-j)a_k (ij)ak
那么如果 i × a i − j × a j &gt; ( i − j ) a k i\times a_i-j\times a_j&gt;(i-j)a_k i×aij×aj>(ij)ak,那么跳到 i i i是更合法的。
移项,只要 i × a i &gt; ( i − j ) a k + j × a j i\times a_i&gt;(i-j)a_k+j\times a_j i×ai>(ij)ak+j×aj就更合法。
T = m a x ( a k , a j ) T=max(a_k,a_j) T=max(ak,aj),有 ( i − j ) a k + j × a j ≤ ( i − j ) T + j × T (i-j)a_k+j\times a_j\leq (i-j)T+j\times T (ij)ak+j×aj(ij)T+j×T
不等号右侧合并同类项得 ( i − j ) a k + j × a j ≤ ( i − j + j ) T (i-j)a_k+j\times a_j\leq (i-j+j)T (ij)ak+j×aj(ij+j)T,即 ( i − j ) a k + j × a j ≤ T i (i-j)a_k+j\times a_j\leq Ti (ij)ak+j×ajTi
因为 a i &gt; T a_i&gt;T ai>T(已经假设 i i i是最大价值的点),所以 i × a I &gt; T i i\times a_I&gt;Ti i×aI>Ti
所以有 i × a i &gt; T i ≥ ( i − j ) a k + j × a j i\times a_i&gt;Ti\geq (i-j)a_k+j\times a_j i×ai>Ti(ij)ak+j×aj
证毕。

那么直接单调队列记录最大值即可。


代码:

#include <cstdio>
#include <queue>
#define mp make_pair
using namespace std;

int n,ans,x,y,last;
deque<pair<int,int> > q;

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		while (q.size()&&q.back().first<x) q.pop_back();  //保证单调
		q.push_back(mp(x,i));
	}
	while (q.size())
	{
		x=q.front().first;
		y=q.front().second;
		q.pop_front();
		ans+=x*(y-last);  //计算价值
		last=y;
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值