二分、三分、01

[USACO 2009 Dec S]Music Notes
1.题意就是查找对应时间点正在弹奏的音是哪个,先前缀和一下,然后upper_bound即可

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};

void solve()
{
     int n,q;
     cin>>n>>q;
     vector<int>ve(n+1);
     for(int i=1;i<=n;i++) cin>>ve[i];
     for(int i=1;i<=n;i++) ve[i]+=ve[i-1];
     while(q--)
     {
         int x;
         cin>>x;
         int k=upper_bound(all(ve),x)-ve.begin();
         cout<<k<<endl;
     }
}


signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

完全平方数
1.先把1-50000的平方数放进一个数组里面,然后使用两次lower_bound查询边界,边界相减即可
2.但是注意4 4或者16 16这种边界相同的特殊情况,结果+1即可

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};

void solve()
{
     int n,l,r;
     vector<int>ve;
     cin>>n;
     ve.push_back(0);
     for(int i=1;i<=50000;i++)
     {
         ve.push_back(i*i);
     }
     while(n--)
     {
         cin>>l>>r;
        int k1=lower_bound(all(ve),l)-ve.begin();
        int k2=lower_bound(all(ve),r)-ve.begin();
       int  ans=k2-k1;
       int f=*lower_bound(all(ve),r);
       if(f==r) ans++;
        cout<<ans<<endl;
         
         
         
     }
}


signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

[NOIP2015]跳石头
1.二分写模版,check里面用挪走石头的次数来验证是否合法,当遇见一段差值比mid大的时候我们就挪一次。

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};

int l,n,m;
vector<int>ve,d;
bool check(int x)
{
    //检查一下如果当前这段差值比我们的x来的小
    //那么我们就需要挪走这块石头增大这段差值
    //挪走当前这块石头的话temp不需要改,还是上一块的值
    //如果没有挪,那么就要更新这个temp
    int now=0,temp=ve[0];
    for(int i=1;i<=n+1;i++){
        if(now>m) return 0;
        if(ve[i]-temp<x)
        {
            now++;
        }else {
            temp=ve[i];
        }
    }
  
    return 1;
    
}

void solve()
{

    cin>>l>>n>>m; 
    if(n==0) {
        cout<<l;
        return;
    }
    //而且注意特判当没有石头的情况
    //注意把0和l放进去
    ve.push_back(0);
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        ve.push_back(x);
    }
    ve.push_back(l);

      int l=1,r=1e12;
      while(l<r)
      {
          int mid=(l+r+1)>>1;
          if(check(mid))   l =mid;
          else r=mid-1;
      }
      cout<<l;
      
    
    
}


signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

华华给月月准备礼物
1.二分答案,枚举最大长度,check里面每个数除最大长度看总和是否大于等于k即可

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
int ve[200010];
int n,k;
bool check(int x)
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=ve[i]/x;
    }
    if(sum>=k) return 1;
     return 0;
    
}

void solve()
{

    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>ve[i];
    int l=1,r=1e9;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }
    cout<<r;
    
}


signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

[CQOI2010]扑克牌
1.二分答案,二分的mid是总共可以有几套牌,check里应满足当所有的x-ai加起来是小于m的,并且不能大于x,x-ai是需要补充的joker的牌数,小于m说明牌是够的,如果大于了x,至少有一套牌里用了2张joker是不合法的

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
int n,m;
int c[50000];
bool check(int x)
{
    int sum=0;
    for(int i=0;i<n;i++)
    {
       if(x-c[i]>0) sum+=x-c[i] ;//需要补的joker牌的数量
    }
    if(sum<=m&&sum<=x)//1.满足joker牌数小于m 2.满足joker牌数不能大于x
    return 1;//因为如果比x大,说明至少有一套牌里用了两张joker
    return 0;
    
}

void solve()
{
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>c[i];
    int l=1,r=1e9;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }
    cout<<r;
}


signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

posted on 2024-07-12 09:25  swj2529411658  阅读(14)  评论(0)    收藏  举报

导航