http://arc066.contest.atcoder.jp/tasks/arc066_c?lang=en
这类题目是我最怕的,没有什么算法,但是却很难想,
这题的题解是这样的,观察到,在+号里面添加括号是没用的,
那么看看减号,任意两个相邻减号,
比如1 - 20 + 8 - 13 - 5 + 6 + 7 - 8
可以变成1 - (20 + 8 - 13) + 5 + 6 + 7 + 8
为什么后面的可以全部都变成正数呢?
因为可以这样变,1 - (20 + 8 - 13 - (5 + 6 + 7) - 8)
所以,观察到,这个观察到,到底需要多大的脑洞呢?
暴力枚举任意一对相邻的减号,只有其里面包括的数字全部变成负数为代价,使得后面的数字全部变正。
暴力枚举即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> const int maxn = 1e5 + 20; LL perfixSum[maxn], absSum[maxn]; vector<int>pos; void cut(LL &val, int pos1, int pos2) { if (pos1 > pos2) return; val -= absSum[pos2] - absSum[pos1 - 1]; } void work() { int n; scanf("%d", &n); int val; scanf("%d", &val); perfixSum[1] = val; absSum[1] = val; for (int i = 2; i <= n; ++i) { int val; char op; cin >> op; scanf("%d", &val); if (op == '+') { perfixSum[i] = perfixSum[i - 1] + val; } else { perfixSum[i] = perfixSum[i - 1] - val; pos.push_back(i); } absSum[i] = absSum[i - 1] + val; } LL ans = perfixSum[n]; for (int i = 0; i <= (int)pos.size() - 2; ++i) { int p1 = pos[i], p2 = pos[i + 1]; LL tans = absSum[n] - absSum[p2 - 1]; tans += perfixSum[p1]; cut(tans, p1 + 1, p2 - 1); ans = max(ans, tans); } cout << ans << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif // int val; // scanf("%d", &val); // cout << val << endl; work(); return 0; }