2 6 2 2 1 -3 5 1 -2 3 6 3 4 1 -3 5 1 -2 3
6 7
枚举连续序列的初始点 并找到【初始点+A-1,初始点+B-1】区间中的sum[i]的最大值 更新ANS即可
复杂度N*(B-A)
但是我们可以看出 在找最大值时 这个区间是固定不动的,而且随着枚举初始点向左移,所以可以用单调队列来维护这个区间最大值
是单调队列的一个常用法
单调队列介绍在这里
http://blog.csdn.net/justmeh/article/details/5844650
1.不加二分
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 const int maxn=500000+5; using namespace std; struct node { long long num; int pos; }; long long N,A,B; long long a[maxn],sum[maxn]; node queue[maxn]; int s=1,t=0; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } void input() { s=1;t=0; scanf("%d%d%d",&N,&A,&B); for(int i=1;i<=N;i++) { scanf("%I64d",&a[i]); sum[i]=sum[i-1]+a[i]; } } void PUSH(long long aa,int bb) { while(t!=s-1&&queue[t].num<=aa) t--; queue[++t].num=aa,queue[t].pos=bb; } void solve() { long long ans; for(int i=A;i<=B;i++) PUSH(sum[i],i); ans=queue[s].num-sum[0]; for(int i=2;i+A-1<=N;i++) { if(i+B-1<=N) PUSH(sum[i+B-1],i+B-1); while(queue[s].pos<i+A-1) s++; if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1]; } printf("%I64d\n",ans); } int main() { // init(); int T; cin>>T; while(T--) { input(); solve(); } return 0; }
2.加二分
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 const int maxn=500000+5; using namespace std; struct node { long long num; int pos; }; long long N,A,B; long long a[maxn],sum[maxn]; node queue[maxn]; int s=1,t=0; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } void input() { s=1;t=0; scanf("%d%d%d",&N,&A,&B); for(int i=1;i<=N;i++) { scanf("%I64d",&a[i]); sum[i]=sum[i-1]+a[i]; } } int FIND(int s,int t,int p) { int m; while(s<t) { int m=(s+t)/2; if(queue[m].num<p) t=m; else s=m+1; } if(queue[s].num<=p) return s-1; else return s; } void PUSH(long long aa,int bb) { int k=0; if(s>t) queue[++t].num=aa,queue[t].pos=bb; else { t=FIND(s,t,aa); queue[++t].num=aa,queue[t].pos=bb; } } void solve() { long long ans; for(int i=A;i<=B;i++) PUSH(sum[i],i); ans=queue[s].num-sum[0]; for(int i=2;i+A-1<=N;i++) { if(i+B-1<=N) PUSH(sum[i+B-1],i+B-1); while(queue[s].pos<i+A-1) s++; if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1]; } printf("%I64d\n",ans); } int main() { // init(); int T; cin>>T; while(T--) { input(); solve(); } return 0; }