有一个长度为 n 的序列(ai),每个数对应着一个罚值 bi,之后开始从 a 序列的第一个数字开始取数,只要拿的 a 序列数字之和不小于对应的 b 序列数字之和,则所拿数字合法。
求在保证可以拿到的数字之和最大的情况下,初始最少要拿几个数放到序列后面去
我们将 b 与处理一下,将罚值与奖值加起来,这样只要判断是否贡献大于0即可
只要当前区间 a 序列之和不小于 b 序列之和,e 就继续往后扩展,扩展后如果所拿数字之和大于已有最大值则更新答案,然后把 s 移动到 e+1 继续上述过程
const int N=2e6+5;
int n,m,t;
int i,j,k;
int a[N],b[N];
int main()
{
IOS;
while(cin>>n){
for(i=1;i<=n;i++){
cin>>a[i];
a[n+i]=a[i];
}
for(i=1;i<=n;i++){
cin>>b[i];
b[i]=a[i]-b[i];
b[i+n]=b[i];
}
int s=1,e=1,ans=0,penalty=0,sum=0,maxx=0;
while(s<=n){
//penalty=0,e=s,sum=0;
while(e<=n*2 && penalty+b[e]>=0){
penalty+=b[e];
sum+=a[e];
e++;
}
if(sum>maxx){
maxx=sum;
ans=s-1;
}
//s=e+1;
penalty-=b[s];
sum-=b[s];
s++;
}
cout<<ans<<endl;
}
//PAUSE;
return 0;
}
第一次用注释部分跑的,但是不大清楚网上大牛们为什么要将 s 移动到 e+1 继续跑,感觉不大严谨,后来自己写的竟然更快。。
可能数据很水