Educational Codeforces Round 28 Four Segments 前缀和 + 思维

来源:互联网 发布:数据库文件提取数据 编辑:程序博客网 时间:2024/05/22 16:43


点击打开链接


题意:

the value of res = sum(0, delim0) - sum(delim0, delim1) + sum(delim1, delim2) - sum(delim2, n) is maximal.

 sum(l, r) 左闭右开.

 

思路:


数据范围这么小,毫无疑问想一发暴力就可以。

这里我们可以考虑枚举一个i,然后先维护一个 sum(0,j)-sum(j,i) 的最大值.在维护一个sum(i,j)-sum(j,n)的最大值.

最后维护一个和的最大值就好

值得注意的是:      这里的区间是左闭右开的区间,这里我们加一个偏移量,即下标从1开始.

那么有: 

[1,j]-[j+1,i] => [0,j)-[j,i)


[i+1,j] -[j+1,n] => [i,j) -[j,n)
 


#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 5e3+10;const ll inf = (1<<60)-1;ll a[maxn],sum[maxn],pre[maxn],suf[maxn];int n,locp[maxn],locs[maxn];int main(){while(cin>>n){for(int i = 0;i <= n+1;++i){pre[i] = suf[i] = -inf;}sum[0] = 0;for(int i = 1;i <= n;++i){scanf("%lld",&a[i]);sum[i] = sum[i-1] + a[i];}for(int i = 0;i <= n;++i){for(int j = 0;j <= i;++j){if(pre[i] < 2*sum[j] - sum[i]){pre[i] = 2*sum[j] - sum[i];locp[i] = j;}}for(int j = i;j <= n;++j){if(suf[i] < 2*sum[j]-sum[i]-sum[n]){suf[i] = 2*sum[j]-sum[i]-sum[n];locs[i] = j;}}}int mx = 0;for(int i = 0;i <= n;++i){if(pre[mx]+suf[mx] < pre[i]+suf[i])mx = i;}printf("%d %d %d\n",locp[mx],mx,locs[mx]);}return 0;}  


第二种写法其实最简单

#include<bits/stdc++.h>using namespace std;const int maxn = 5e3 + 10;typedef long long ll;const ll inf = (1<<60)-1;ll sum[maxn];ll S(int l,int r){return sum[r]-sum[l];}ll a[maxn];int main(){int n;cin>>n;sum[0] = 0;for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i] = sum[i-1]+a[i];} ll ans = -1e18;int d1,d2,d3;for(int i=0;i<=n;i++){ll s1 = -1e18,s2=-1e18;int t1,t2;for(int j=0;j<=i;j++){if(S(0,j)-S(j,i)>s1){s1=S(0,j)-S(j,i);t1=j;}}for(int j=i;j<=n;j++){if(S(i,j) - S(j,n)>s2){s2=S(i,j)-S(j,n);t2=j;}}if(ans < s1+s2){ans = s1+s2;d1=t1,d2=i,d3=t2;}}printf("%d %d %d\n",d1,d2,d3);return 0;}

阅读全文
0 0
原创粉丝点击