2018QBXT刷题游记(26)

【2018QBXT刷题游记】

Day8 TEST9
T2 game

【问题描述】
小 N 和小 A 在玩这样的一个游戏:给定初始数列 Q,小 N 先把某个前缀
(可以为空) 的数字全部乘上 -A,小 A 再把某个后缀 (可以为空) 的数字全部乘上 -B,小 N 想让最后所有数的和尽量大,小 A 想让最后所有数的和尽量的小。
小 A 绝对不会失误,所以小 N 想找到某个方法使得最后所有数的和尽量大,请帮助小 N 求出最大的值是多少吧。

【分析】记前缀和为 Si,设小 N 取前 K 个数,小 A 取第 p 个数之后
的所有数,分相交和不相交,最终总和为:

( 1 + B ) ∗ S p − ( 1 + A ) ∗ S k − B ∗ S n ( k &lt; = p ) (1+B)*S_p-(1+A)*S_k-B*S_n (k&lt;=p) (1+B)Sp(1+A)SkBSn(k<=p)

B ∗ ( A + 1 ) ∗ S k ⋅ ? A ∗ ( B + 1 ) ∗ S p ? B ∗ S n ( k &lt; p ) B*(A + 1)*S_k·?A*(B+1)*S_p?B*S_n(k&lt;p) B(A+1)Sk?A(B+1)Sp?BSn(k<p)

当对于任意一个k,两式中的 S k S_k Sk项和 S n S_n Sn是不变的,

所以 S p S_p Sp项的大小直接影响整个式子的值。

观察到,式1中 S p S_p Sp项为正,所以小A希望 S p S_p Sp越小越好,

同理,式2中 S p S_p Sp越大越好。

所以只需要预处理出 ∀ k , m i n ( i )   ( k &lt; = i &lt; = n ) , m a x ( i )   ( 1 &lt; = i &lt; = k ) \forall k,min (i)\ (k&lt;=i&lt;=n), max(i) \ (1&lt;=i&lt;=k) k,min(i) (k<=i<=n),max(i) (1<=i<=k)

注意细节处理:如哪里是0-n,哪里是1-n

哦对,ans的绝对值需要非常非常大……别问我怎么知道的

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 1000007
#define ll long long
ll sum[MAXN],l[MAXN],r[MAXN],ans,tmp;
int n,a,b;
int main(){
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
    ans=-99999999999999999;
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;i++){
		scanf("%lld",&tmp);
		sum[i]=sum[i-1]+tmp;
		l[i]=max(l[i-1],sum[i]);
	}
	r[n]=sum[n];
	for(int i=n-1;i!=-1;i--)r[i]=min(r[i+1],sum[i]);
	for(int i=0;i<=n;i++){
		ans=max(ans,min((1+b)*r[i]-(a+1)*sum[i]-b*sum[n],b*(a+1)*sum[i]-a*(b+1)*l[i]-b*sum[n]));
	}
	printf("%lld\n",ans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值