1.思路:采用二分法解决。
代码:
#include<iostream>
#include<vector>
using namespace std;
int chick(vector<int>&a,int number){
int l=0;
int r=a.size()-1;
int mid;
while(l<=r){
mid=(l+r)/2;
if(a[mid]==number){
return 1;
}else if(a[mid]<number){
l=mid+1;
}else{
r=mid-1;
}
}
return 0;
}
int main() {
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
int q;
cin>>q;
for(int i=0;i<q;i++){
int x;
cin>>x;
if(chick(a,x)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
return 0;
}
总结:善于使用二分法解题会轻松一些。
2.思路 :遍历数组,利用sort函数寻找目标值的头尾,之后利用二者的差值找到与B相差C的A的个数,再相加
代码:
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
int left(const vector<int>& a, int num,int n){
int l=0,r=n-1,ans=-1;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]==num)
{
r=mid-1;
ans=mid;
}
else if(a[mid]>num)r=mid-1;
else if(a[mid]<num)l=mid+1;
}
return ans;
}
int right(const vector<int>& a, int num,int n){
int l=0,r=n-1,ans=-1;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]==num)
{
l=mid+1;
ans=mid;
}
else if(a[mid]>num)r=mid-1;
else if(a[mid]<num)l=mid+1;
}
return ans;
}
int main()
{
int n,c;
cin>>n>>c;
vector<int> a;
for(int i=0;i<n;i++)
{
int num;
cin>>num;
a.push_back(num);
}
sort(a.begin(),a.end());
long long int count=0;
for(int j=0;j<n;j++)
{
int ans1=0,ans2=0;
int num=a[j]+c;
ans1=left(a,num,n);
ans2=right(a,num,n);
if(ans1!=-1&&ans2!=-1)
count=(ans2-ans1+1)+count;
}
cout<<count;
return 0;
}
总结:此类题型可以用排序完后找头尾的位置然后判断其组数。
3.思路:利用二分查找寻找值,再检查该值是否足够分给k个小朋友来寻找最佳答案
代码:
#include <iostream>
#include <vector>
using namespace std;
bool check(int sideLength, const vector<pair<int, int>>& chocolates, int K) {
int total = 0;
for (const auto& chocolate : chocolates) {
total += (chocolate.first / sideLength) * (chocolate.second / sideLength);
}
return total >= K;
}
int main() {
int N, K;
cin >> N >> K;
vector<pair<int, int>> chocolates(N);
for (int i = 0; i < N; ++i) {
cin >> chocolates[i].first >> chocolates[i].second;
}
int left = 1, right = 100000;
while (left < right) {
int mid = (left + right + 1) / 2;
if (check(mid, chocolates, K)) {
left = mid;
} else {
right = mid - 1;
}
}
cout << left << endl;
return 0;
}
总结:此类寻找最佳答案的问题可以通过二分答案解决
4.思路:用c[i]=a[i]+b[i],并用sort找到最小的c[i],再利用二分以最终手写的牌是否超过m从1到最小的c[i]寻找最佳答案
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n;
int a[N];
int b[N];
long long m;
bool judge(int x) {
long long s = 0;
for (int i = 1; i <= n; i++) {
if (x - a[i] <= b[i]) {
s += max(x - a[i], 0);
}
else return false;
}
if (s <= m) return true;
return false;
}
int main() {
cin >> n >> m;
int l = 0x3f3f3f3f;
int r = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
l = min(l, a[i]);
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
r = max(r, b[i] + a[i]);
}
int ans;
while (l <= r) {
int mid = l + r >> 1;
if (judge(mid)) {
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
cout << ans << '\n';
return 0;
}
总结:此类寻找最佳答案的问题可以通过二分答案解决,关键在于判断好二分的范围和查找的条件
5.思路:先利用二分答案找到最短时间,再以抄书时间是否超过该最短时间为条件寻找每个人开始抄书的序号和结束抄书的序号,再倒序输出
代码: #include<bits/stdc++.h>
using namespace std;
long long n,m;
long long a[505],x[510],y[510];
bool check(int s)
{
int num=1,t=0;
for(int i=n;i>=1;i--)
{
if(t+a[i]>s)t=0,num++;
t+=a[i];
}
return num<=m;
}
int f(int l,int r)
{
int mid;
while(l+1<r)
{
mid=(l+r)/2;
if(check(mid))r=mid;
else l=mid;
}
return r;
}
int main()
{
long long l=0,r=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
r+=a[i];
l=max(l,a[i]);
}
int s=f(l,r);
int t=0,num=1;
for(int i=1;i<=m;i++)
{
x[i]=y[i]=0;
}
y[1]=n;
for(int i=n;i>=1;i--)
{
if(t+a[i]>s)
{
t=0;
x[num]=i+1;
y[++num]=i;
}
t+=a[i];
}
x[num]=1;
for(int i=m;i>=1;i--)
{
cout<<x[i]<<" "<<y[i]<<endl;
}
}
总结:此题在寻找最佳答案的基础上需要输出每个人抄的书,因此还可以用到二分答案,再通过分析题目条件输出正确答案即可
6.思路:采用采用for循环来判断来回时所需高度
代码:#include <bits/stdc++.h>
#define N 100005
using namespace std;
int n,T,h[N],ans;
int main() {
scanf("%d%d",&n,&T);T<<=1;
for(int i=1;i<n;++i) scanf("%d",&h[i]);
for(int i=1,j=0,sum=0;i<n;++i) {
while(j<n&&sum<T) sum+=h[++j];
ans=max(ans,j-i+1);
sum-=h[i];
}
printf("%d\n",ans);
return 0;
}
总结:善于利用循环来解决问题