1二分正宗
#include<iostream>
#include<stdio.h>
using namespace std;
int erfen(int a[],int left,int right,int x)
{
int mid;
while(left<=right)//等于号是为了能取到
{
mid=(right+left)/2;//此处应防止堆栈溢出(当超过int的一般的时候)
if(a[mid]>x) right=mid-1;//范围越小越好
else if(a[mid]<x) left=mid+1;
else return mid;
}
return -1;
}
int main()
{
const int n=10;
int a[n]={1,3,4,6,7,8,10,11,12,15};
printf("%d %d\n",erfen(a,0,n-1,6),erfen(a,0,n-1,9));
return 0;
}
2快速幂
typedef long long ll;
ll kuaisumi(ll a,ll b,ll m)
{
if(b==0) return 1;//别忘了
else if(b%2==1) return a*kuaisumi(a,b-1,m)%m;//此处对m求余是对的,防止
else
{
ll mul =kuaisumi(a,b/2,m);
return mul*mul%m;
}
}
1.1转换二分,先排序再二分,不要读错题意(题目意思是定左动右)(而且和前缀和结合的一个小综合题)
/*
E. Kaguya's Birthday Party
Kaguya is going to celebrate her birthday in her mansion. She wants to invite her friends to the birthday party.
Kaguya has n friends, each friend will agree to go to the party if Kaguya asks. Each friend is characterized by the amount of money he or she has and the friendship factor in respect to Kaguya. Kaguya doesn't want any friend to feel poor compared to somebody else. A friend feels poor if in the party there is someone who has at least d units of money more than he or she does. Also, Kaguya wants the total friendship factor of the members of the party to be maximum. As her maid, you should help her!
输入格式:
The first line of the input contains two space-separated integers, n and d ( 1≤n≤10
5
, 1≤d≤10
9
) — the number of Kaguya's friends and the minimum difference between the amount of money in order to feel poor, respectively.
Next n lines contain the descriptions of Kaguya's friends, the (i+1)-th line contains the description of the i-th friend of type m
i
, s
i
(0≤m
i
,s
i
≤10
9
) — the amount of money and the friendship factor, respectively.
输出格式:
Print the maximum total friendship factor that can be reached.
输入样例1:
4 5
75 5
0 100
150 20
75 1
输出样例1:
100
输入样例2:
5 100
0 7
11 32
99 10
46 8
87 54
输出样例2:
111
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
typedef long long ll;
struct node
{
ll qian,frien;
}Node[100010];
bool cmp(node a,node b)
{
return a.qian<b.qian;
}
ll q[100010];
using namespace std;
int main()
{
int n,d;
scanf("%d %d",&n,&d);
for(int i=1;i<=n;i++) scanf("%lld %lld",&Node[i].qian,&Node[i].frien);
sort(Node+1,Node+n+1,cmp);
Node[0].frien=0;
for(int i=1;i<=n;i++)
{
q[i]=Node[i].qian;
Node[i].frien+=Node[i-1].frien;
}
ll ans=-1;
ll anst;
for(int i=1;i<=n;i++)
{
ll shang=Node[i].qian+d;
ll* upper=lower_bound(q+1,q+n+1,shang);
ll up=upper-q-1;
if(up==i) anst=Node[up].frien-Node[up-1].frien;//相等的时候比较特殊
else anst=Node[up].frien-Node[i-1].frien;// 包含两头的应该这样写
ans=max(anst,ans);
}
printf("%lld",ans);
}
3.1二分答案(板子)砍树(坑死我了)
/*
题目描述
伐木工人米尔科需要砍倒M米长的木材。这是一个对米尔科来说很容易的工作,因为他有一个漂亮的新伐木机,可以像野火一样砍倒森林。不过,米尔科只被允许砍倒单行树木。
米尔科的伐木机工作过程如下:米尔科设置一个高度参数H(米),伐木机升起一个巨大的锯片到高度H,并锯掉所有的树比H高的部分(当然,树木不高于H米的部分保持不变)。米尔科就行到树木被锯下的部分。
例如,如果一行树的高度分别为20,15,10和17,米尔科把锯片升到15米的高度,切割后树木剩下的高度将是15,15,10和15,而米尔科将从第1棵树得到5米,从第4棵树得到2米,共得到7米木材。
米尔科非常关注生态保护,所以他不会砍掉过多的木材。这正是他为什么尽可能高地设定伐木机锯片的原因。帮助米尔科找到伐木机锯片的最大的整数高度H,使得他能得到木材至少为M米。换句话说,如果再升高1米,则他将得不到M米木材。
输入格式
第1行:2个整数N和M,N表示树木的数量(1<=N<=1000000),M表示需要的木材总长度(1<=M<=2000000000)
第2行:N个整数表示每棵树的高度,值均不超过1000000000。所有木材长度之和大于M,因此必有解。
输出格式
第1行:1个整数,表示砍树的最高高度。
输入输出样例
输入 #1复制
5 20
4 42 40 26 46
输出 #1复制
36
*/
//大模拟技巧(如果实在觉得模拟困难不好理解就用笔算一算,列数字或者画图)
//本题二分的思路告诉我们,不需排序也能二分 ,单调就能做 (二分答案)神奇的将最值问题转化为判定问题
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
long long tree[1000010];
int n;
long long m;
long long sum=0;
bool check(int mid)//成功的砍伐木头
{
for(int i=1;i<=n;i++)
{
if(tree[i]>mid) sum+=tree[i]-mid;
}
if(sum>=m) return true;
else return false;
}
int main()
{
long long left=0;
scanf("%d %lld",&n,&m);
long long longe=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&tree[i]);
longe=max(longe,tree[i]);
}
long long mid=(left+longe)/2;
long long ans=-1;
while(left<=longe)
{
mid=(left+longe)/2;
if(check(mid))
{
ans=mid;
left=mid+1;
}
/*
else if(sum>m) left=mid+1;
else break;
*/
else longe=mid-1;
sum=0;
}
printf("%lld",ans);
}
3.2跳石头(经典题目)
/*
洛谷经典跳石头
题目背景
一年一度的“跳石头”比赛又要开始了!
题目描述
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NN 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 MM 块岩石(不能移走起点和终点的岩石)。
输入格式
第一行包含三个整数 L,N,ML,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L \geq 1L≥1 且 N \geq M \geq 0N≥M≥0。
接下来 NN 行,每行一个整数,第 ii 行的整数 D_i( 0 < D_i < L)D
i
?
(0<D
i
?
<L), 表示第 ii 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
输出格式
一个整数,即最短跳跃距离的最大值。
输入输出样例
输入 #1复制
25 5 2
2
11
14
17
21
输出 #1复制
4
说明/提示
输入输出样例 1 说明:将与起点距离为 22和 1414 的两个岩石移走后,最短的跳跃距离为 44(从与起点距离 1717 的岩石跳到距离 2121 的岩石,或者从距离 2121 的岩石跳到终点)。
另:对于 20\%20%的数据,0 ≤ M ≤ N ≤ 100≤M≤N≤10。
对于50\%50%的数据,0 ≤ M ≤ N ≤ 1000≤M≤N≤100。
对于 100\%100%的数据,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,0000≤M≤N≤50,000,1≤L≤1,000,000,000。
最大值的最小值,最小值的最大值,有序,数据范围大,判定比直接暴力简单一百倍,就可以二分答案
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll l,n,m;
ll shitou[50001];
ll duan[50001];
bool check(ll mid)//这里贪心的过程稍微有点难想
{
ll shu=0;
ll countt=0;
ll count=0;
for(ll i=1;i<=n+1;i++)
{
shu+=duan[i];
if(shu>=mid)
{
shu=0;
count+=countt;
countt=0;
}
else countt++;
}
count+=countt;
if(count>m) return false;
else return true;//返回true并不代表说是一定存在,而是有可能还能更加优化
}
int main()
{
scanf("%lld %lld %lld",&l,&n,&m);
duan[0]=0;
ll left=0;
ll right=l;
for(ll i=1;i<=n;i++)
{
scanf("%lld",&shitou[i]);
duan[i]=shitou[i]-shitou[i-1];
}
duan[n+1]=l-duan[n];
ll ans=0;
while(left<=right)
{
ll mid=(left+right)/2;
if(check(mid))
{
ans=mid;
left=mid+1;
}
else right=mid-1;
}
printf("%lld",ans);
return 0;
}