(以下题目均来自洛谷LUOGU)
A.P2249 【深基13.例1】查找(入门)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define rush() int T;cin>>T;while(T--)
#define ll long long
//可用 map 或者 stl-upper_bound
using namespace std;
const int N = 1e7;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int,int> pii;
ll arr[N],num[N];
ll n,m,ans,p = 1;
int find(int x){
int l = 1;
int r = n;
while(l < r){//二分答案 细节关键啊...........
int mid = (l + r) / 2;
if(arr[mid] < ans)l = mid + 1;
else r = mid;
}
if(arr[l] == ans)return l;
return -1;
}
int main(){
FAST;
cin>>n>>m;
for(int i = 1;i <= n;i++)cin>>arr[i];
for(int i = 1;i <= m;i++){
cin>>ans;
num[i] = find(ans);
}
for(int i = 1;i < m;i++)cout<<num[i]<<" ";
cout<<num[m];
return 0;
}
B.P1024 一元三次方程求解(入门)
#include<iostream>
#include<cstdio>
using namespace std;
double a,b,c,d;
double f(double x){return (a * x * x * x + b * x * x + c * x + d);}
int main(){
ios::sync_with_stdio(false);
double cur1,cur2,mid;
cin>>a>>b>>c>>d;
double left = -100,right = -99,k = 0,l,r;
while(k < 3 && right <= 101){
l = left,r = right;
cur1 = f(l),cur2 = f(r);
if(f(l) == 0){
printf("%.2lf ",l);//l是由 left继承过来的 写成f的格式 left一定要设置成ll 血的教训 求你了没有下次
k++;
}
else if(cur1 * cur2 < 0){
k++;
while(r - l >= 0.001){
mid = (l + r) / 2.0;
if(f(mid) * f(r) <= 0)l = mid;
else r = mid;
}
printf("%.2lf ",l);
}
left++;
right++;
}
return 0;
}
C.P1102 A-B 数对(入门)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define rush() int T;cin>>T;while(T--)
#define ll long long
//不开ll见祖宗
using namespace std;
const int N = 2e5 + 100;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int,int> pii;
ll arr[N],sum[N];
ll n,c;
int search(ll x){
ll cnt = 1;
for(int i = x - 1;i >= 1;i--){
if(arr[i] == arr[x])cnt++;
else break;
}
for(int i = x + 1;i <= n;i++){
if(arr[i] == arr[x])cnt++;
else break;
}
return cnt;
}
int main(){
FAST;
cin>>n>>c;
for(int i = 1;i <= n;i++)cin>>arr[i];
sort(arr + 1,arr + n + 1);
for(int i = n;i > 1;i--){
if(i <= n - 1 && arr[i] == arr[i + 1]){
sum[i] = sum[i + 1];
continue;
}
ll l = 1,r = i - 1;
ll ans = arr[i] - c;
while(l < r){
int mid = (l + r) / 2;
if(arr[mid] < ans)l = mid + 1;
else if(arr[mid] > ans)r = mid - 1;
else{
l = mid;
break;
}
}
if(arr[l] == ans)sum[i] = search(l);
}
ll cur = 0;
for(int i = 1;i <= n;i++)if(sum[i])cur += sum[i];
cout<<cur;
return 0;
}
D.P1873 砍树(普及)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define rush() int T;cin>>T;while(T--)
#define ll long long
using namespace std;
const int N = 10e6 + 1000;
ll n,m,term,ans[N],maxn = 0;
ll check(int mid){
ll sum = 0;
for(int i = 1;i <= n;i++){
if(ans[i] - mid > 0)sum += ans[i] - mid;
}
return sum;
}
int main(){
cin>>n>>m;
for(int i = 1;i <= n;i++){
cin>>ans[i];
if(ans[i] > maxn)maxn = ans[i];
}
ll l = 1,r = maxn;
while(l <= r){
int mid = (l + r) / 2;
if(check(mid) >= m)l = mid + 1;
else r = mid - 1;
}
cout<<r<<endl;
return 0;
}
E.P2440 木材加工(普及)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define rush() int T;cin>>T;while(T--)
#define ll long long
//二分答案的模板多样 细节最重要!
using namespace std;
const int N = 1e5 + 100;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int,int> pii;
ll arr[N];
ll n,k,maxn,sum;
ll check(ll x){
ll cnt = 0;
for(int i = 1;i <= n;i++)cnt += arr[i] / x;
return cnt;
}
int main(){
FAST;
cin>>n>>k;
for(int i = 1;i <= n;i++){
cin>>arr[i];
maxn = max(maxn,arr[i]);
sum += arr[i];
}
if(sum < k){cout<<"0";return 0;}
if(sum < 2 * k){cout<<"1";return 0;}
ll l = 1,r = maxn;
while(l < r - 1){
ll mid = (l + r) / 2;
if(check(mid) >= k)l = mid;
else r = mid;
}
cout<<l;
return 0;
}
F.P2678 跳石头(普及)
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 100;
//一开始我的思路是这样的 先维护一个优先队列记录每一个跳跃距离
//在check函数里面 我固定做 m 次 加法模拟移走岩石 查询队首元素是否大于mid
//但是我不会传递队列作为形参 导致我的check会永久改变原先队列
//题解的做法是保留原先的距离 在check里面计算跳跃距离
int ans[N];
int l,n,m,maxn = 0;
//priority_queue<int, vector<int>, greater<int> >ans;
int check(int mid){
int time = 0,term = 0;
for(int i = 1;i <= n;i++){
while(ans[i] - term < mid && i <= n)time++,i++;
term = ans[i];
}
return time;
}
int main(){
cin>>l>>n>>m;
for(int i = 1;i <= n;i++)cin>>ans[i];
//maxn = max(maxn,a[i]);
ans[++n] = l;
//maxn = max(maxn,l - a[n]);
//ans.push(a[1]),ans.push(l - a[n]);
//for(int i = 2;i <= n;i++)ans.push(a[i] - a[i - 1]);
//sort(ans + 1,ans + n + 2);
int low = 1,high = l;
while(low <= high){
int mid = (low + high) / 2;
if(check(mid) <= m)low = mid + 1;
else high = mid - 1;
}
cout<<high<<endl;
return 0;
}
G.P1182 数列分段 Section II(普及)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define rush() int T;cin>>T;while(T--)
#define ll long long
//二分答案的模板多样 细节最重要!
using namespace std;
const int N = 1e7;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int,int> pii;
ll arr[N];
ll n,m,maxn;
ll check(ll x){
ll sum = 0,cnt = 0;
for(int i = 1;i <= n;i++){
if(sum + arr[i] <= x)sum += arr[i];
else sum = arr[i],cnt++;
}
return cnt;
}
int main(){
FAST;
ll sum = 0,maxn = -1;
cin>>n>>m;
for(int i = 1;i <= n;i++){
cin>>arr[i];
sum += arr[i];
maxn = max(maxn,arr[i]);
}
ll l = maxn,r = sum;//这次错误在于端点问题
while(l <= r){
ll mid = (l + r) / 2;
if(check(mid) >= m)l = mid + 1;
else r = mid - 1;
}
cout<<l;
return 0;
}
H.P3853 [TJOI2007]路标设置(普及+)
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define ms(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define rush() int T;cin>>T;while(T--)
#define ll long long
using namespace std;
const int N = 1e5 + 100;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int,int> pii;
//几天的二分练习独立AC的题目寥寥无几....
//二分题注重细节: lr的选取, while边界确定,check函数准确性,数据范围.........
int arr[N],len[N],cur[N];
int L,n,k;
int check(int x){
int cnt = 0;
for(int i = 2;i <= n;i++)
if(arr[i] - arr[i - 1] >= x){
cnt += (arr[i] - arr[i - 1]) / x;
if((arr[i] - arr[i - 1]) % x == 0)cnt--;
}
if(cnt > k)return 0;
return 1;
}
int main(){
FAST;
int sum = 0,maxn = -1;
cin>>L>>n>>k;
for(int i = 1;i <= n;i++){
cin>>arr[i];
if(i >= 2)len[i - 1] = arr[i] - arr[i - 1];
}
int l = 1,r = L;
while(l < r){
int mid = (l + r) / 2;
if(!check(mid))l = mid + 1;
else r = mid;
}
cout<<r;
return 0;
}