水题,不过细节坑死,WA了很多发。。。
思路:先从起点不断往两侧走,
左端边界lb为max(1LL,p-t),右端边界为min(n,p+t)。
如果rb-lb <= M 结果显而易见。
反之,如果M是偶数,就让两个人从起点分别走M/2步,往后就是先向左再向右还是先向右再向左的问题,
枚举就好了。
如果M是奇数,两个人中其中一人要走M/2+1步,同样枚举即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const LL maxn = 100005;
LL n,p,m,t,lb,rb,val[maxn],sum[maxn];
LL ans;
void o(LL l,LL r,LL k){
LL i,lt,rt;
for(i = 0;i <= k;i++){
rt = r + i;
if(rt > n) break;
lt = max(1LL,l - k + 2LL*i);
lt = min(lt,l);
ans = max(ans,sum[rt]-sum[lt-1LL]);
//cout<<"right:"<<lt<<" "<<rt<<" "<<ans<<endl;
}
for(i = 0;i <= k;i++){
lt = l - i;
if(lt < 1) break;
rt = min(n,r + k - 2LL*i);
rt = max(r,rt);
ans = max(ans,sum[rt]-sum[lt-1LL]);
//cout<<"left:"<<lt<<" "<<rt<<" "<<ans<<endl;
}
}
int main(){
LL i,j,L,R,D;
while(~scanf("%lld%lld",&n,&p)){
ans = 0;
for(i=1;i<=n;i++){
scanf("%lld",&val[i]);
sum[i] = sum[i-1] + val[i];
}
scanf("%lld%lld",&m,&t);
lb = max(1LL,p-t);rb = min(n,p+t);
if(rb - lb <= m){
printf("%lld\n",sum[rb]-sum[lb-1]);
}else{
if(m&1){
L = max(1LL,p - (m >> 1));R = min(n,p + (m >> 1));
D = t - (m >> 1) - 1;
if(L == 1){
o(L,R+1,D);
}
else if(R == n){
o(L-1,R,D);
}else {
o(L-1,R,D);o(L,R+1,D);
}
}else{
L = max(1LL,p - (m >> 1));R = min(n,p + (m >> 1));
D = t - (m >> 1);
ans = sum[R] - sum[L-1];
o(L,R,D);
}
//cout<<L<<" "<<R<<" "<<D<<endl;
printf("%lld\n",ans);
}
}
return 0;
}