每日刷题04

问题描述
  JiaoShou在爱琳大陆的旅行完毕,即将回家,为了纪念这次旅行,他决定带回一些礼物给好朋友。
  在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子。
  这些石子很漂亮,JiaoShou决定以此为礼物。
  但是这N个石子被施加了一种特殊的魔法。
  如果要取走石子,必须按照以下的规则去取。
  每次必须取连续的2*K个石子,并且满足前K个石子的重量和小于等于S,后K个石子的重量和小于等于S。
  由于时间紧迫,Jiaoshou只能取一次。
  现在JiaoShou找到了聪明的你,问他最多可以带走多少个石子。
输入格式
  第一行两个整数N、S。
  第二行N个整数,用空格隔开,表示每个石子的重量。
输出格式
  第一行输出一个数表示JiaoShou最多能取走多少个石子。
样列输入
  8 3
  1 1 1 1 1 1 1 1
样列输出
  6
样列解释
  任意选择连续的6个1即可。
  这道题蓝桥杯给的解题方法是贪心算法,但是有一种方法计算速度更加快也就是二分法。对给定的序列一直求子集最后l与r不相等时,也就是最大的长度序列:具体代码如下:
#include
using namespace std;
typedef long long ll;//定义一个long long类型变量
const ll N = 1e5;
ll mark[N]={0};
ll n;
ll s;//这三个都设置为全局因为数据可能很大
bool meetS(ll mid){ //用来判断mid也就是当前所选择的中间mark是否左边和右边都有满足之和等于s的序列
for(int i = mid;i<=n;i++){
if(mark[i]-mark[i-mid]<=s &&mark[i+mid]-mark[i]<=s){
return true;
}
}
return false;

}
int main(){
int r,l,mid;
cin>>n>>s;
for(int i = 1;i<=n;i++)
{
cin>>mark[i];
mark[i]+=mark[i-1];

}
l=1;r=n;
while(l<=r){//递归进行寻找最长序列和小于s的序列
    mid = (r+l)/2;
    if(meetS(mid)){
        l = mid+1;
    }else{
        r = mid-1;
    }
}
cout<<(2*r);
return 0;

}

你可能感兴趣的:(蓝桥杯,算法,职场和发展)