https://codeforces.com/contest/1405/problem/B
题意:给你一个和为0的数组,每次可以选择两个不同的数 ai和aj,使ai 减1,使 aj 加1,如果i<j,操作免费,否则代价为1,求最小代价。
思路:开始想树状数组动态处理差的和。写了发现不用这么麻烦。
从头开始遇到正的数就累加,如果碰到负数,就能给尽可能给,最后剩下来的就是答案。
考场上想的是从后往前思考,碰到了正数就加上去,碰到了负数也加上去,这样就相当于模拟了免费的过程(把正的合并,负的合并,正和负的抵消),中间出现的最大值就是最终答案。比如-1 -2 3 3 3,后往前遍历到的总和9是没法免费的。
比如 4 -9 8 4 -2 5,先5最大值,然后能抵消一个-2,然后又加到4和8,这里就代表不能免费的最多是这么多。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
#define lowbit(x) ((x)&(-x))
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
LL a[maxn],tree[maxn];
LL n;
void solve()
{
LL ans=-0x3f3f3f3f;
LL sum=a[n];
ans=max(ans,sum);
for(LL i=n-1;i>=1;i--)
{
sum+=a[i];
ans=max(ans,sum);
}
cout<<ans<<endl;
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL t;cin>>t;
while(t--)
{
cin>>n;
for(LL i=1;i<=n;i++) cin>>a[i];
solve();
}
return 0;
}