题目描述
今天 qwb 要参加一个数学考试,这套试卷一共有 n 道题,每道题 qwb 能获得的分数为 ai,qwb 并不打算把这些题全做完,他想选总共 2k 道题来做,并且期望他能获得的分数尽可能的大,他准备选 2 个不连续的长度为 k 的区间,即 [L,L+1,L+2,....,L+k−1],[R,R+1,R+2,...,R+k−1](R⩾L+k) 。
输入描述
第一行一个整数 T(T⩽10),代表有 T 组数据。
接下来一行两个整数 n,k(1⩽n⩽200000)(1⩽k,2k⩽n)。
接下来一行 n 个整数 a1,a2,...,an(−100,000⩽ai⩽100000)。
输出描述
输出一个整数,qwb 能获得的最大分数。
示例1
输入
2
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1
输出
6
7
分析
定义 sum[i]=j=i∑i+k−1a[j] ,每次枚举 L 得 sum[L],然后查询区间 [L+k,n] 内长度为 k 的区间最大值,即查询 L+k⩽i⩽n−k+1maxsum[i],这显然是一个简单的 RMQ 问题,可用 ST 表维护 sum[i] 的区间最大值。sum[L]+L+k⩽i⩽n−k+1maxsum[i] 有可能成为答案,O(n) 枚举 L,即可得到答案。
代码
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #include<cstdio> #include<algorithm> #include<iostream> #define N 200003 #define ll long long using namespace std; int a[N]; ll sum[N]; int _log2[N]; ll f[N][18]; int n,k; int nn;
void pre() { _log2[1]=0; int i; for(i=2;i<N;i++) _log2[i]=_log2[i>>1]+1; }
void init() { int i,j; for(i=1;i<=nn;i++) f[i][0]=sum[i]; for(j=1;(1<<j)<=nn;j++) { for(i=1;i+(1<<j)-1<=nn;i++) { f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); } } } int main() { int _; pre(); for(cin>>_;_;_--) { scanf("%d%d",&n,&k); int i; for(i=1;i<=n;i++) scanf("%d",a+i); nn=n-k+1; ll temp=0; for(i=1;i<=n;i++) { if(i<=k) temp+=a[i]; else { sum[i-k]=temp; temp=temp-a[i-k]+a[i]; } } sum[nn]=temp; init(); ll ans=-1000000000000000000; for(i=1;i<=n-2*k+1;i++) { int l=i+k,r=nn; int s=_log2[r-l+1]; ans=max(ans,sum[i]+max(f[l][s],f[r-(1<<s)+1][s])); } printf("%lld\n",ans); } return 0; }
|