二分+贪心(7)

二分+贪心

我的天,最近也不知道忙点什么,课也基本没有,还是累的要死。
这篇写二分和贪心。
先说二分吧。二分:二分查找和二分搜索,二分查找:是一种非常高效的搜索方法,主要原理是每次搜索可以抛弃 一半的
值来缩小范围。
怎么说呢,二分真的是不难,关键在于你得能看出他是二分思想,有些题真的是想不到居然能用二分,而且用二分会这么简单。
老规矩,先给一个二分的板子

int L;//左边界 
int R;//右边界 
while(L<=R)
{
	int mid=(L+R)/2; 
	if(a[mid]==k) //k就是想找的那个数 
	{
		flag=mid;
		break;
	}	
	else if(a[mid]>k)
		R=mid-1;
	else
		L=mid+1;
}

再给一个二分的板子题(真的是找不见简单的):
Strange fuction HDU - 2899

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
double f(double x,double y)
{ 
	return (double)6.0*pow(x,7.0)+8.0*pow(x,6.0)+7.0*pow(x,3.0)+5.0*pow(x,2.0)-y*x;
}
double g(double x,double y)
{
	return 42.0*pow(x,6.0)+48*pow(x,5.0)+21*pow(x,2.0)+10*x-y;
}
int main()
{
	double x,y;
	int T;
	cin>>T;
	while(T--)
	{
		cin>>y;
		double l=0.0,r=100.0;
		double mid;
		while(r-l>1e-6)
		{
			mid=(l+r)/2;
			if(g(mid,y)<0)
				l=mid;
			else
				r=mid;
		}
		printf("%.4f\n",f(mid,y));
	}
	return 0;
}
//读者自己理解吧,反正也不算难。

拓展:
lower_bound(), upper_bound()
真香!!!这个是真的香。

在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

看下边的代码理解一下哈:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() 
{
	//从小到大的排序数组
	int a[12]={3,4,5,5,5,6,6,17,18,19,110,111};
	cout<<lower_bound(a,a+12,17)<<endl;      //0x6ffdfc
	cout<<lower_bound(a,a+12,17)-a<<endl;    //7
	cout<<a[lower_bound(a,a+12,17)-a]<<endl; //17 
	
	cout<<upper_bound(a,a+12,17)<<endl;      //0x6ffdf0
	cout<<upper_bound(a,a+12,17)-a<<endl;    //8
	cout<<a[upper_bound(a,a+12,17)-a]<<endl; //18
	
	//从大到小的排序数组
	int b[11]={9,8,8,8,7,6,5,4,3,2,1}; 
	cout<<lower_bound(b,b+11,7,greater<int>())<<endl;        //0x6ffd80
	cout<<lower_bound(b,b+11,7,greater<int>())-b<<endl;      //4
	cout<<b[lower_bound(b,b+11,7,greater<int>())-b]<<endl;   //7
	
	cout<<upper_bound(b,b+11,7,greater<int>())<<endl;        //0x6ffd54  
	cout<<upper_bound(b,b+11,7,greater<int>())-b<<endl;      //5
	cout<<b[upper_bound(b,b+11,7,greater<int>())-b]<<endl;   //6
	return 0;
}

先来个板子题(虽然可以二分,但是建议感受一下真香):
pairs HDU - 5178

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100010];
int main()
{
	ios::sync_with_stdio(false);
	int t;
	ll n,k;
	cin>>t;
	while(t--)
	{
		ll ans=0;
		cin>>n>>k;
		for(int i=0;i<n;i++)
			cin>>a[i];
		sort(a,a+n);
		for(ll i=0;i<n;i++)
		{
			ll l=lower_bound(a,a+n,a[i]-k)-a;
			ll r=upper_bound(a,a+n,a[i]+k)-a-1;
			ans=ans+(r-l);
		}
		cout<<ans/2<<endl;	
	}
	
	return 0;
}

二分+贪心先关题目:
Pie HDU - 1969
Best Cow Line POJ - 3617
Trailing Zeroes (III) LightOJ - 1138
The Frog’s Games HDU - 4004 (难)
湫湫系列故事——消灭兔子 HDU - 4544(难)
Strange fuction HDU - 2899
Can you find it? HDU - 2141
Radar Installation POJ - 1328 (难)
Aggressive cows POJ - 2456
River Hopscotch POJ - 3258 (难)

再说贪心,反正在我看来,贪心就是玩了个脑子数学加C++基础,要熟练的运用这些东西,贪心才能贪的得心应手。也没有什么具体的方法板子,反正做出来就行。就像上面的题,每个题都用到贪心。还有就是用贪心做题一定要把方方面面考虑周到,否则很容易WA掉。

发布了41 篇原创文章 · 获赞 5 · 访问量 2282

猜你喜欢

转载自blog.csdn.net/mumuhaoshuai/article/details/100550654