问题描述
JiaoShou在爱琳大陆的旅行完毕,即将回家,为了纪念这次旅行,他决定带回一些礼物给好朋友。
在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子。
这些石子很漂亮,JiaoShou决定以此为礼物。
但是这N个石子被施加了一种特殊的魔法。
如果要取走石子,必须按照以下的规则去取。
每次必须取连续的2*K个石子,并且满足前K个石子的重量和小于等于S,后K个石子的重量和小于等于S。
由于时间紧迫,Jiaoshou只能取一次。
现在JiaoShou找到了聪明的你,问他最多可以带走多少个石子
在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子。
这些石子很漂亮,JiaoShou决定以此为礼物。
但是这N个石子被施加了一种特殊的魔法。
如果要取走石子,必须按照以下的规则去取。
每次必须取连续的2*K个石子,并且满足前K个石子的重量和小于等于S,后K个石子的重量和小于等于S。
由于时间紧迫,Jiaoshou只能取一次。
现在JiaoShou找到了聪明的你,问他最多可以带走多少个石子
样列输入
8 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
样列输出
6
样列解释
任意选择连续的6个1即可。
思路:二分答案。每次二分一个答案,如果当前的答案能满足存在一个序列S1+...+Sk<=s并且Sk+1+...+S2k<=s,就继续从mid后面找,如果不满足就从mid前面找。把满足的结果保存下来,最后保存的结果就是要求的结果。时间复杂度为n(logn),能跑完。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int Max=1000003; 5 const int mod=10007; 6 ll sum[Max]; 7 int n; 8 ll s; 9 int kk(int k) 10 { 11 for(int i=k; i<=n&&i+k<=n; i++) 12 if(sum[i]-sum[i-k]<=s&&sum[i+k]-sum[i]<=s)return 1;//存在序列i~i+2*k-1满足条件 13 return 0; 14 } 15 int main() 16 { 17 18 cin>>n>>s; 19 for(int i=1; i<=n; i++) 20 { 21 ll a; 22 cin>>a; 23 sum[i]=sum[i-1]+a; 24 } 25 int k=0; 26 int l,r; 27 l=1; 28 r=n/2;//不能超过序列的一半 29 while(l<=r) 30 { 31 int mid=(l+r)/2; 32 if(kk(mid)) 33 { 34 l=mid+1; 35 k=mid; 36 } 37 else r=mid-1; 38 } 39 cout<<k*2<<endl; 40 }