2016 UESTC Training for Dynamic Programming B - 柱爷与最大区间和 最大区间和推广、前缀和、枚举间隔点
来源:互联网 发布:远距离网络对讲系统 编辑:程序博客网 时间:2024/05/18 02:00
B - 柱爷与最大区间和
Time Limit: 1000/1000MS (Java/Others) Memory Limit: 131071/65535KB (Java/Others)
柱爷爱思考,凡事喜欢举一反三,常常能想到别人没想过的问题。
比如最大区间和这个问题:在一数列上选出一段区间,使得这段区间和最大。
柱爷想:如果选出两段区间(不相邻)会怎样呢?
柱爷很快想到了答案,你呢?
Input
第一行输入一个数N,表示数组的长度。
第二行输入N个数,表示各元素的值。
数据保证:
3 <= N <= 500000
-100 < Ai < 100
Output
输出一个数,表示数组的两段区间(不相邻)之和的最大值。
Sample input and output
62 3 -3 3 -2 4
10
Hint
对于样例,选择$2,3$和$3,-2,4$这两个区间,和为$10$.
PS.区间不相邻是指前一个区间的最后一个数和后一个区间的第一个数不相邻
Source
2016 UESTC Training for Dynamic Programming
My Solution
最大区间和推广、预处理、打表、枚举间隔点
//本来实验过先找到一个最大区间,然后得到ans 和左右边界, 在里面找到最小符区间然后减去, 但这样显然不对,没办法^_^
从左到右扫一遍,从右到做扫一遍,处理好前缀和suml[maxn] 和 sumr[maxn],
并分别 O(n)的预处理出 1 ~ i 的最大连续区间和L[i], 和 i ~ n-1 的最大连续区间和 R[i]
然后枚举间隔点, i = 1 ~ n-2; ans = max(ans, L[i-1] + R[i+1];
复杂度O(n);
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 500000 + 8;int val[maxn], suml[maxn], sumr[maxn], L[maxn], R[maxn];/*5-1 -1 -1 -1 0*/int main(){ #ifdef LOCAL freopen("a.txt", "r", stdin); #endif // LOCAL int N, maxs = 0; memset(val, 0, sizeof val); scanf("%d", &N); for(int i = 0; i < N; i++){ scanf("%d", &val[i]); } maxs = val[0]; int last = 0; //!last 要从0开始 for(int i = 0 ; i < N ; i++){ last = max(0,last)+val[i]; maxs = max(maxs,last); L[i] = maxs;//cout<<L[i]<<" "; } maxs = val[N-1]; last = 0; //!last 要从0开始 for(int i = N-1 ; i >= 0 ; i--){ last = max(0,last)+val[i]; maxs = max(maxs,last); R[i] = maxs;//cout<<L[i]<<" "; } int ans = -0x3f3f3f3f;//!!!!!!选两个区间的最大连续和,可能还是一个很小的负数 for(int i = 1; i+1 < N; i++){ ans= max(ans, L[i-1]+R[i+1]); } printf("%d", ans); return 0;}/*#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 500000 + 8;int val[maxn], sum[maxn];int minsum(int x, int y){ int v, L, R, mins; if(y-x==1) return val[x]; int m = x + (y-x)/2; mins = min(minsum(x, m), minsum(m,y)); v = 0; L = val[m-1]; for(int i = m-1; i >= x; i--) L = min(L, v += val[i]); v = 0; R = val[m]; for(int i = m; i < y; i++) R = min(R, v += val[i]); return min(mins, L+R);}/*int maxsum(int x, int y){ int v, L, R, maxs; if(y-x==1) return val[x]; int m = x + (y-x)/2; maxs = max(maxsum(x, m), maxsum(m,y)); v = 0; L = val[m-1]; for(int i = m-1; i >= x; i--) L = max(L, v += val[i]); v = 0; R = val[m]; for(int i = m; i < y; i++) R = max(R, v += val[i]); return max(maxs, L+R);}//int main(){ #ifdef LOCAL freopen("a.txt", "r", stdin); #endif // LOCAL int N, maxs = 0, maxi , mini = 0; memset(val, 0, sizeof val); scanf("%d", &N); for(int i = 0; i < N; i++){ scanf("%d", &val[i]); if(i!= 0) sum[i] = sum[i-1] + val[i]; else sum[i] = val[i]; } int maxs=val[0]; int mins=sum[0]; //保存当前遇到的最小S,当mins=S[0]或其他的,都不对。 for(int j=1;j<N;j++) { if(maxs <= sum[j]-mins){ maxs = sum[j]-mins; maxi = j; } if(mins > sum[j] && j < maxi){ mins = sum[j]; mini = j+1;//cout<<"mini=="<<endl; } } if(maxs < sum[N-1]){ maxs=sum[N-1]; maxi = N-1; } printf("mins=%d\n",mins); printf("%d\n",maxs); cout<<mini<<" "<<maxi+1<<endl; printf("%d", maxs-minsum(mini, maxi+1)); return 0;}*//*#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 500000 + 8;int sum[maxn];int main(){ #ifdef LOCAL freopen("a.txt", "r", stdin); #endif // LOCAL int N, val, maxs, maxi,mins, mini; memset(sum, 0, sizeof sum); scanf("%d", &N); for(int i = 0; i < N; i++){ scanf("%d", &val); if(i!= 0) sum[i] = sum[i-1] + val; else sum[i] = val; } maxs=sum[N-1], maxi=N-1,mins=sum[N-1], mini=N-1; for(int i = N-1; i >= 0; i--){ maxs = max(maxs, sum[i]); mins = min(mins, sum[i]); } printf("%d", maxs- (mins <= sum[N-1] - maxs ? mins : sum[N-1] - maxs)); return 0;}*/
Thank you!
------from ProLights
- 2016 UESTC Training for Dynamic Programming B - 柱爷与最大区间和 最大区间和推广、前缀和、枚举间隔点
- 2016 UESTC Training for Dynamic Programming D - 柱爷的恋爱 区间dp、记忆化搜索
- CDOJ1357--柱爷与最大区间和
- cdoj柱爷与最大区间和
- 线段树-区间单个点更新-区间和-区间最大
- 2016 UESTC Training for Dynamic Programming N - 柱爷与子序列 这题和N题有些相似之处、用了树状数组
- CDOJ-2016-B-柱爷与最大区间和
- hdoj5280最大区间和
- 最大子区间和
- hoj5586 区间和最大
- 2016 UESTC Training for Dynamic Programming A - 柱爷与咸鱼神功 0-1背包
- 【cdoj 1357】柱爷与最大区间和
- 【CDOJ 1357】柱爷与最大区间和
- 2015 UESTC Training for Dynamic Programming 男神的礼物(区间dp)
- 2016 UESTC Training for Dynamic Programming(1)
- cf#22-B-Bargaining Table-枚举+贪心+dp(最大连续区间和)
- 前缀和:区间和
- 时间复杂度-----最大区间和
- 如何下载YouTube网站的视频
- 69道Spring面试题和答案
- MySQL存储过程+游标+触发器
- android 性能优化
- HDU NO.4162 Shape Number(最小表示法循环输出字符串)
- 2016 UESTC Training for Dynamic Programming B - 柱爷与最大区间和 最大区间和推广、前缀和、枚举间隔点
- gh0st的IOCP模型分析
- 1002 Problem B
- MySQL服务启动提示window无法启动MySQL服务 错误1067:进程意外终止
- No3.组合查询--机房收费
- JDBC 与 MyBatis
- BestCoder Round #83(HDU 5680)
- Ubuntu13.10系统 apt-get update失败解决办法
- Ubuntu下配置opencv-2.4.9