二分、三分、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) 收藏 举报
浙公网安备 33010602011771号