1. 程式人生 > >2018QBXT刷題遊記(26)

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 < = p ) (1+B)*S_p-(1+A)*S_k-B*S_n (k<=p)

B ( A + 1 ) S k ? A ( B + 1 ) S p ? B S n ( k < p ) B*(A + 1)*S_k·?A*(B+1)*S_p?B*S_n(k<p)

當對於任意一個k,兩式中的 S k S_k 項和 S n S_n 是不變的,

所以 S p S_p 項的大小直接影響整個式子的值。

觀察到,式1中 S p S_p 項為正,所以小A希望 S p S_p 越小越好,

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

所以只需要預處理出 k , m i n ( i )   ( k < = i < = n ) , m a x ( i )   ( 1 < = i < = k ) \forall 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;
}