Array Cancellation(思维-反向思考)

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108446333