西安DAY1之二分,三分,折半与位运算

首先说二分
二分法最初用于对有序数列进行查找,其时间复杂度仅为O(log n)。
事实上,广义的二分法可用于解决一大类问题。
考虑一个广义的单调递增函数F(x),我们要求一个最小的x0 使得F(x0)>= y0。
初始时,我们知道L0 <=x0<=R0。
二分的每一步中,设Li<=x0<=Ri 满足F(Li) < 0 而F(Li)>=0。
取Mi=(Li+Ri)/2:
(1) 若F(Mi) < 0,则令Li+1 = Mi,Ri+1 = Ri;
(2) 若F(Mi) > 0,则令Li+1 = Li,Ri+1 = Mi。
随着二分次数的增加,x0 被限制在越来越小的区间内,精度成指数的提高。
这便是二分的原理。
当x0 的取值范围是[1; n] 中的整数时,二分进行O(log n)次便可确定x0 的值。
二分的代码实现具有一定技巧性,见例题。
电压
有2nk 块电池供给n 台机器,其中每台机器有两部分,每部分各需要k 块电池。
现在每块电池有一个电压,k 块电池并联的总电压简单地认为是k 块电池电压的最小值。
一套机器能否工作,取决于机器两部分的电压差u。
问u 最小是多少,使得合理的分配电池,能让每台机器机器两部分的电压差不超过u。
2nk<=1e6,且任意电池电压为1 到1e9 的整数。

二分答案
考虑对于每个当前的u,如何判断是否存在分配方案。
将电池电量从低到高排序后,从电压最低的电池开始,如果前两块电池电压差已大于u,则失败。
每选出一对电压差不超过u 的电池,另外(2k-2) 块电池就可以随便选了。如果能最终选出n,那么返回成功。
上代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define N 1000100
#define jd (c<='9'&&c>='0')
#define gg c=getchar()
inline int read()
{
	int f=0,x=1;char gg;
	for(;!jd;gg)if(c=='-')x=0;
	for(;jd;gg)f=(f<<1)+(f<<3)+c-48;
	return x?f:-f;
}
int n,k,a[N],cnt;
inline bool check(int x)
{
	for(int p=1,q=0;q<n;p++)
    {
        if(p-1>q*2*k)return 0;
        if(a[p+1]-a[p]<=x)p++,q++;
    }
    return 1;
}
int main()
{
	n=read();k=read();
	for(int i=1;i<=n*k*2;i++)a[i]=read();
	sort(a+1,a+n*k*2+1);
	int l=0,r=1e9+1;
	while(l<r&&cnt<60)
	{
		cnt++;
		int mid=(l+r)>>1;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	printf("%d",l);
	return 0;
}

第二题
Usaco 2005 feb
aggressive cows 愤怒的牛
农夫 John 建造了一座很长的畜栏,它包括NN (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,…,xN (0 <= xi <= 1,000,000,000). 但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?

继续二分答案
如果可行则更新左区间
代码不放了
之后是三分
它用于求一个上凸函数的极大值。
和二分一样,我们有一个初始的区间L0<=x0<=R0。
每一步中,对于当前区间Li<=x0<=Ri,我们取两个点
Pi = (2Li+Ri)/3 ; Qi = (Li+2Ri)/3:
(1) 若F(Pi) < F(Qi),那么必有Pi<=x0<=Ri,故下一步区间变为Li+1 = Pi; Ri+1 = Ri;
(2) 若F(Pi) > F(Qi),那么必有Li<=x0<=Qi,故下一步区间变为Li+1 = Li; Ri+1 = Qi;
(3) 若F(Pi) = F(Qi),那么必有Pi<=x0<=Qi,故下一步区间变为Li+1 = Pi; Ri+1 = Qi。
无论哪种情况,每迭代一次,区间长度将至少缩小为原来的2/3,这是指数变化的。
随着三分次数的增加,x0 被限制在越来越小的区间内,精度成指数的提高。
当x0 的取值范围是[1; n] 中的整数时,三分同样进行O(log n) 次便可确定x0 的值。
由于三分类似二分所以不放题了我懒
位运算
就是
&与
|或
~非
^异或
<<左移 >>右移
如题
给定2n + 1 个正整数,其中有n 个数出现了2 次,只有一
个数出现了一次,试快速找出出现一次的数。
n<=1e6。

其实是道脑筋急转弯
边读入边异或
最后剩下的数就是了
map?祝神犇AK NOIPTh Au K.rp++
最后是折半
就是优化暴力
比如原来复杂度O(2^30)
折半后就是O(2^15*2)妈妈再也不用担心我TLE啦!
比如枚举6种搭配
只需枚举前三种和后三种的搭配
根据题意排序
之后呢?
二分!
今天就说到这里吧
蒟蒻到神犇的路漫漫其修远兮
吾将上下而求索
另:
神犇友链
1:yhk
David_alwal:传送门
2:pjt
Superme_Ariy:传送门
每日不定期更新~~(或者不更新)~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值