acm寒假集训第二讲总结

1.二分查找

思路:
使用二分法查找答案即可

代码:

#include <iostream>
#include <string.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	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,l=0,r=n-1,is=0;
		cin>>x;
		while(r>=l)
		{
			int mid=(l+r)/2;
			if(a[mid]==x)
			{
				cout<<"Yes"<<endl;
				 is=1;
				 break;
			}
			else if(a[mid]>x)
			{
				r=mid-1;
			}
			else if(a[mid]<x)
			{
				l=mid+1;
			}
		}
		if(is==0)
		{
			cout<<"No"<<endl;
		}
	}
	return 0;
}

2.A-B 数对

思路:
A-B=C相对于A=B+C,遍历所有可行的B得出A并用二分法查找,先要将输入进行排序,排序后查找对每个确定的B对应的第一个A和最后一个A的位置即可得出有几个A

代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
	long long int n,c,cnt=0;
	cin>>n>>c;
	long long int arry[n];
	for(long long int i=0;i<n;i++)
	{
		cin>>arry[i];
	}
	sort(arry,arry+n);
	long long int a,b=arry[0];
	a=b+c;
	for(long long int i=1;i<n&&a<=arry[n-1];i++)
	{
		long long int p1,p2;
		long long int l1,r1,l2,r2,mid1,mid2,ans1,ans2;
		l1=l2=0;r1=r2=n-1;
		while(l1<=r1)
		{
			mid1=(l1+r1)/2;
			if(arry[mid1]>=a) 
			{
				r1=mid1-1;
				ans1=mid1;
			}
			else l1=mid1+1;
		}
		p1=ans1;
		while(l2<=r2)
		{
			mid2=(l2+r2)/2;
			if(arry[mid2]<=a) 
			{
				l2=mid2+1;
				ans2=mid2;
			}
			else r2=mid2-1;
		}
		p2=ans2;
		cnt+=p2-p1+1;
		b=arry[i];
		a=b+c;
	}
	cout<<cnt;
	return 0;
}

3.分巧克力

思路:
首先找到巧克力中的最长边长(不一定要用到每块巧克力),1~最长边长就是答案区间,具有单调性,使用二分法查找符合条件中最大的即可

代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
struct date
{
	long long int x,y;
};
int check(long long int x,struct date *a,long long int n,long long int k);
int main()
{
	long long int n,k,i,j;
	cin>>n>>k;
	struct date a[n];
	long long int b[2*n];
	for(i=0,j=0;i<n,j<2*n;i++,j+=2)
	{
		cin>>a[i].x>>a[i].y;
		b[j]=a[i].x;b[j+1]=a[i].y;
	}
	sort(b,b+2*n);
	long long int ar[b[2*n-1]];
	for(i=0;i<b[2*n-1];i++)
	{
		ar[i]=i+1;
	}
	long long int l,r,mid,ans;
	l=0;r=b[2*n-1]-1;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(check(ar[mid],a,n,k))
		{
			l=mid+1;
			ans=mid;
		}
		else
		{
			r=mid-1;
		}
	}
	cout<<ans+1;
	return 0;
}

int check(long long int x,struct date *a,long long int n,long long int k)
{
	long long int cnt=0;
	for(int i=0;i<n;i++)
	{
		cnt+=(a[i].x/x)*(a[i].y/x);
	}
	if(cnt>=k) return 1;
	else return 0;
}

4.卡牌

思路:
计算最大的ai+bi,答案区间为0~max(ai+bi),使用二分法查找符合要求的最大值即可

代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
int check(long long int x,long long int *ai,long long int *bi,long long int n,long long int m);
int main()
{
	long long int n,m,i;
	cin>>n>>m;
	long long int ai[n],bi[n];
	for(i=0;i<n;i++)
	{
		cin>>ai[i];
	}
	for(i=0;i<n;i++)
	{
		cin>>bi[i];
	}
	long long int max=-1;
	for(i=0;i<n;i++)
	{
		if(ai[i]+bi[i]>max)
		{
			max=ai[i]+bi[i];
		}
	}
	long long int l,r,mid,ans;
	l=0;r=max;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(check(mid,ai,bi,n,m))
		{
			l=mid+1;
			ans=mid;
		}
		else
		{
			r=mid-1;
		}
	}
	cout<<ans;
	return 0;
}

int check(long long int x,long long int *ai,long long int *bi,long long int n,long long int m)
{
	long long int cnt=0;
	for(long long int i=0;i<n;i++)
	{
		if(bi[i]<x-ai[i])
		{
			return 0;
		}
		if(ai[i]<x)
		{
			cnt+=(x-ai[i]);
		}
	}
	if(cnt<=m) return 1;
	else return 0;
}

学习总结:
通过这次的学习,我学习到了二分法的原理和基本模板,还学习了二分查找和二分答案,二分法有效提高了代码的效率,在讲解时也了解到了高效的代码实现方法。

posted @   asdadsdf  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示