1. 程式人生 > 實用技巧 >【GMOJ6804】模擬jerry

【GMOJ6804】模擬jerry

題目

題目連結:https://gmoj.net/senior/#main/show/6804
眾所周知,Jerry 鼠是一隻非常聰明的老鼠。Jerry 聰明到它可以計算 64 位有符號整形數字的加減法。現在,Jerry 寫下了一個只由非負整數和加減號組成的算式。它想給這個算式新增合法的括號,使得算式的結果最大。這裡加減法的運算優先順序相同,和我們在日常生活中接觸到的一樣,當沒有括號時,先算左邊的,再算右邊的。比如,算式 (1+2)+3−(4−5)+6 是合法的,但是 )1+2( 和 (−)1+2 以及 −(1)+2 都是不合法的。

思路

括號巢狀括號最多隻會巢狀兩層,因為巢狀三層之後等價於沒有套。
發現只有在 - 後面加括號才會改變答案,所以我們固定在 + 後邊一定不能加括號,設 \(f[i][j]\)

表示處理到第 \(i\) 個數字,在第 \(j\) 層括號的最大和。如果 \(j=1\) 需要變號。
分類當前符號簡單轉移即可。時間複雜度 \(O(n)\)

思路

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=200010;
int Q,n,x;
ll f[N][3];
char ch[3];

int main()
{
	freopen("jerry.in","r",stdin);
	freopen("jerry.out","w",stdout);
	scanf("%d",&Q);
	while (Q--)
	{
		f[1][1]=f[1][2]=-1000000000000000000LL;
		scanf("%d%lld",&n,&f[1][0]);
		for (int i=1;i<n;i++)
		{
			scanf("%s%d",ch,&x);
			if (ch[0]=='+')
			{
				f[i+1][0]=max(f[i][0]+x,f[i][1]-x);
				f[i+1][1]=max(f[i][1]-x,f[i][2]+x);
				f[i+1][2]=f[i][2]+x;
			}
			else
			{
				f[i+1][0]=max(f[i][0]-x,f[i][1]+x);
				f[i+1][1]=max(f[i][0]-x,max(f[i][1]+x,f[i][2]-x));
				f[i+1][2]=max(f[i][1]+x,f[i][2]-x);
			}
		}
		printf("%lld\n",max(f[n][0],max(f[n][1],f[n][2])));
	}
	return 0;
}