题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3627
这个题目是个贪心,不过开始一看感觉细节挺多,分开处理比较麻烦,仔细想想这些细节可以统一
当时间和两者之间的距离没达到极限之前一定都往两边走
走完之后如果还有时间,分三种情况,全拿左边的,全拿右边的,两边都拿
假设最优结果已经知道,左边多少全部一次取完,右边多少也一次性取完(先后顺序分两种情况)
接下来就是分时间,分左边多少右边多少,这个一共就十万,直接枚举一下就搞定了
这个题目不需要考虑边界问题,边界问题可以统一,计算越界做后还原就OK了!
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 150000
#define LL long long
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
LL str[maxn];
int n,p,m,t;
int init(int n){
str[0]=0;
for(int i=1;i<=n;i++) str[i]+=str[i-1];
return 0;
}
LL cal_ans(int l,int r){
l=MAX(1,l);
r=MIN(r,n);
return str[r]-str[l-1];
}
int main(){
int i,j,k,l,r,max_l,max_r,now,temp;
LL ans,re_ans;
while(scanf("%d",&n)!=EOF){
scanf("%d",&p);
for(i=1;i<=n;i++) scanf("%lld",&str[i]);
init(n);
l=r=p;
scanf("%d%d",&m,&t);
now=m;
while(now>=2 && t>0){
l--,r++;
t--;
now-=2;
}
ans=0;
for(i=1;i<=t;i++){
max_r=r+i;
temp=r+i-m-(t-i);
max_l=MIN(l,temp);
re_ans=cal_ans(max_l,max_r);
ans=MAX(ans,re_ans);
}
for(i=1;i<=t;i++){
max_l=l-i;
temp=l-i+m+(t-i);
max_r=MAX(r,temp);
re_ans=cal_ans(max_l,max_r);
ans=MAX(ans,re_ans);
}
if(t==0) ans=cal_ans(l,r);
printf("%lld\n",ans);
}
return 0;
}