D. Rating System
正解写挂不要太典
题面
https://codeforces.com/contest/1845/problem/D
做法一
官方做法 假设最终的答案是 $k$,那么一定可以找出一个区间 $[l,r]$,使得在题目的规则下 $rating_l = rating_r = k$,并且区间和小于零,这段区间就是对答案贡献最大的区间(因为对答案的贡献相当于加上被减掉的这部分)。 $Prof.$ 显然 $rating_l = k, rating_r \ge k$。若 $rating_r > k$ 那么必然在原序列中存在一段区间和大于 的区间,这段区间被包括在 $[l,r]$,那么这段区间对答案的贡献一定不是最大的。 因此我们只要找到区间和最小的一段区间,$k$ 即为左端点 $l$ 前的前缀和。 代码见官方题解
做法二
考场上写挂的做法,其实只有一个细节要处理。 显然 $k$ 应该是原序列的前缀和序列中的一项 $sum[i]$,满足 $sum[j] < sumi$,当 $k$ 取 $sum[i]$ 时的贡献即为 $sum[i]-min(sum[j])(j \ge i)$ 特殊情况:原始序列 $-1 \ 3$。 解决方法:只需要在原始序列前添加一项 $0$ 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <cstdio>
int t; int n; long long a[300005]; long long smin[300005];
long long min(long long a,long long b) { return a<b?a:b; }
int main() { scanf ("%d",&t); while (t--) { scanf ("%d",&n); for (int i=1;i<=n;i++) scanf ("%lld",&a[i]); for (int i=1;i<=n;i++) a[i]+=a[i-1]; long long ans=0,m=0; smin[n]=a[n]; for (int i=n-1;i>=0;i--) smin[i]=min(a[i],smin[i+1]); for (int i=0;i<=n;i++) { long long minn=smin[i]; if (a[n]+a[i]-minn>ans) { ans=a[n]+a[i]-minn; m=a[i]; } } printf ("%lld\n",m); } return 0; }
|