一些二分题

POJ2976:

/*
 * POJ2976DroppingTests.cpp
 *
 *  Created on: 2014年7月25日
 *      Author: Prophet
 */
#include<stdio.h>
#include<algorithm>
const int MAX_N = 1000+10;
#define eps 1e-6
using namespace std;

int n,k;
double a[MAX_N],b[MAX_N],t[MAX_N];

double binary_judge(double mid);
int main(){
	while(scanf("%d%d",&n,&k),n+k>0){
		for(int i=0;i<n;i++)
			scanf("%lf",&a[i]);
		for(int i=0;i<n;i++)
			scanf("%lf",&b[i]);

		double l=0.0,r=1.0;
		while(r-l>eps){
			double mid = (l+r)/2;
			if(binary_judge(mid) > 0)//如果用mid作为比例的值大于0,说明mid取小了
				l = mid;
			else
				r = mid;
		}
		//printf("%d\n",(int)(100*r));
		 printf("%.0f\n", l * 100);
	}
}

double binary_judge(double mid){
	for(int i=0;i<n;i++)
		t[i] = a[i] - mid*b[i];
	sort(t,t+n);
	double sum = 0;
	for(int i=k;i<n;i++)
		sum+=t[i];
	return sum;
}


POJ3579:

/*
 * POJ3579Median.cpp
 *
 *  Created on: 2014年7月25日
 *      Author: Prophet
 */
#include<stdio.h>
#include<algorithm>
using namespace std;

const int MAX_N = 100000+10;
int N,m;
int a[MAX_N];

bool binary_judge(int x);
int main(){
	while(scanf("%d",&N)!=EOF){
		for(int i=0;i<N;i++)
			scanf("%d",&a[i]);

		sort(a,a+N);
		m = (N-1)*N/2;
		int l=0 , r=a[N-1]-a[0];
		while(r-l>1){
			int mid = (l+r)/2;
			if(binary_judge(mid))
				l = mid;
			else
				r = mid;
		}
		printf("%d\n",l);
	}
	return 0;
}

bool binary_judge(int x){
	int count=0;//记录以x为差时,满足
	for(int i=0;i<N;i++){
		count += a+N - lower_bound(a,a+N,a[i]+x);
		if(count == 0)
			break;
	}
	/*if(count < m/2)//若有少于一半的差满足条件,则说明选取的x大了
		return false;*/
	return count > m/2;
	/*int cnt = 0;
		for(int i = 0; i < N; i++)
		{
			cnt += a+N - lower_bound(a, a+N, a[i]+x);
			if(cnt == 0) break;
		}
		return cnt > m/2;
		if(cnt < m/2)//若有少于一半的差满足条件,则说明选取的x大了
				return false;
			else
				return true;*/
}



POJ3662:

/*
 * POJ3662TelephoneLines.cpp
 *
 *  Created on: 2014年7月27日
 *      Author: Prophet
 */
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
const int MAX_N = 1000+16;
//const int MAX_V = 10000+10;
const int MAX_L = 1000000;
const int INF = 100000000;

struct edge{
	int to,cost;
};

vector<edge> G[MAX_N];
int d[MAX_N];
int N,P,K;

int dijkstra(int s,int x);
int main(){
	scanf("%d%d%d",&N,&P,&K);
	for(int i=0;i<P;i++){
		int from,to,cost;
		scanf("%d%d%d",&from,&to,&cost);
		from--;
		to--;
		edge e1;e1.to = to;e1.cost = cost;
		edge e2;e2.to = from;e2.cost = cost;
		G[from].push_back(e1);
		G[to].push_back(e2);
	}

	int lb = 0,ub = MAX_L+2;
	while(ub-lb>1)
	{
		int mid = (ub+lb)/2;
		if(dijkstra(0,mid)>K)
			lb = mid;
		else
			ub = mid;
	}
	printf("%d\n",lb>MAX_L?-1:lb);
	return 0;
}

int dijkstra(int s,int x){
	priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > que;
	fill(d,d+N,INF);
	d[s] = 0;
	que.push(pair<int,int>(0,s));

	while(!que.empty()){
		pair<int,int> p = que.top();
		que.pop();
		int v = p.second;
		if(d[v] < p.first)
			continue;
		for(int i=0;i<(int)G[v].size();i++){
			edge e = G[v][i];
			int new_d = d[v] + (e.cost>=x?1:0);
			if(d[e.to]>new_d){
				d[e.to] = new_d;
				que.push(pair<int,int>(d[e.to],e.to));
			}
		}
	}
	return d[N-1];
}


<think> 首先,用户的问是“洛谷整体二分入门”,这似乎是中文的。我需要使用中文回答问。 主是“洛谷整体二分入门”。洛谷是一个在线编程平台,整体二分是一种算法技术,可能指的是整体二分查找或类似的东西。在算法竞赛中,整体二分(有时称为“整体二分法”或“整体二分搜索”)常用于解决多查询问,比如处理多个查询同时进行二分搜索。 用户提到了“入门”,意思是入门级别的目。所以,我应该解释整体二分的基本概念,并提供一个简单的例子或代码实现。 回顾系统提示:我必须在回答完问后,根据用户的问和我的回答,提出3-5个相关问。这些问必须以“§§相关问§§”开头,并且在回答的末尾输出。第一行必须是完整的“§§相关问§§”,不能换行分散。 示例格式显示了一个关于快速排序的回答,然后列出了相关问。 所以,针对这个问,我需要: 1. **回答问**:解释整体二分是什么,提供一个简单的入门例子,并用代码实现(可能是Python,因为示例中是Python)。 2. **提出相关问**:基于我的回答,生成3-5个相关问。 关键点: - **整体二分**:它是一种用于处理多个查询的二分搜索算法优化。例如,在一个有序数组中查找多个元素的位置时,可以一次性处理所有查询,而不是一个个二分搜索,从而减少时间复杂度。 - **入门**:洛谷上可能有相关目,比如经典的“查找数组中多个元素的位置”或类似问。 一个常见的整体二分入门是“静态区间第k小数”或类似问。但为了简单,我可以选择一个基础例子。 假设一个简单例子:有一个排序数组,和多个查询,每个查询要求查找一个值的索引。使用整体二分来高效处理。 代码实现:由于示例是Python,我应该用Python写一个简单的整体二分实现。 结构化我的回答: 1. **解释整体二分**:简要描述它是什么和为什么有用。 2. **提供一个例子**:描述一个简单的场景。 3. **给出代码**:实现整体二分算法。 4. **结束回答**。 然后,输出“§§相关问§§”,后跟3-5个相关问。 相关问必须基于用户的问和我的回答。例如: - 什么是整体二分的时间复杂度? - 整体二分在哪些场景下使用? - 如何扩展整体二分到动态查询? - 洛谷上还有哪些整体二分目? 确保问是中文的。 现在,构建回答: **回答部分:** 整体二分(或称整体二分搜索)是一种高效处理多个二分查找查询的算法。它将所有查询同时处理,通过递归地将查询和数组分割,直到所有查询被解决。常用于算法竞赛中,如查找静态数组中多个值的位置。 一个入门例子:给定一个排序数组arr和一个查询列表queries,每个查询是一个值,要求返回该值在arr中的索引(如果存在),否则返回-1。使用整体二分实现。 Python代码实现: ```python def binary_search_all(arr, queries): # 假设arr是排序好的数组 # queries是一个列表,每个元素是一个查询值 # 返回一个列表,对应每个查询的索引 # 先创建一个结果数组,初始化为-1 result = [-1] * len(queries) # 辅助函数,递归处理查询 def helper(low, high, query_indices): if low > high or not query_indices: return mid = (low + high) // 2 mid_val = arr[mid] # 分割查询索引:小于、等于、大于mid_val left_indices = [] mid_indices = [] right_indices = [] for idx in query_indices: q = queries[idx] if q < mid_val: left_indices.append(idx) elif q == mid_val: result[idx] = mid # 找到匹配 else: # q > mid_val right_indices.append(idx) # 递归处理左半部分和右半部分 helper(low, mid-1, left_indices) helper(mid+1, high, right_indices) # 初始调用,所有查询索引 query_indices = list(range(len(queries))) helper(0, len(arr)-1, query_indices) return result # 示例使用 arr = [1, 3, 5, 7, 9] queries = [5, 2, 9] print(binary_search_all(arr, queries)) # 应输出 [2, -1, 4] ``` 这个代码实现了整体二分,递归地将查询分配到左、中、右部分。当查询值等于当前中点时,直接设置结果。 **相关问部分:** 必须以“§§相关问§§”开头,然后列出3-5个问。例如: 1. 整体二分的时间复杂度是多少? 2. 整体二分与普通二分搜索有什么区别? 3. 在洛谷上,有哪些推荐的整体二分入门目? 4. 整体二分如何处理重复元素? 5. 如何优化整体二分的空间复杂度? 确保输出格式正确:第一行是“§§相关问§§”,然后直接列出问,用数字点号。 最终输出: [回答内容] §§相关问§§ 1. ··· 2. ··· 3. ··· 现在,整合起来。 </think> 整体二分(又称整体二分搜索)是一种用于高效处理多个二分查找查询的算法优化技术。它将所有查询同时处理,通过递归地将查询和数组分割成子问,从而减少重复计算,时间复杂度通常为O((n + q) log n),其中n是数组大小,q是查询数。整体二分常用于算法竞赛中解决静态数组中的多查询问,如查找多个值的位置或统计查询。 在洛谷(Luogu)上,一个典型的入门是“查找排序数组中多个值的索引”。例如,目描述:给定一个排序数组arr和一个查询列表queries,每个查询是一个值,要求返回该值在arr中的索引(如果存在),否则返回-1。使用整体二分实现此功能。 下面是一个Python代码实现示例。该代码递归地将查询分配到左、中、右部分,当查询值等于当前中点时直接设置结果: ```python def binary_search_all(arr, queries): # 初始化结果数组,为每个查询预留默认值-1 result = [-1] * len(queries) # 递归辅助函数,处理从low到high的区间和查询索引列表 def helper(low, high, query_indices): if low > high or not query_indices: return mid = (low + high) // 2 mid_val = arr[mid] # 分割查询索引:根据与mid_val的比较 left_indices = [] # 小于mid_val的查询 mid_indices = [] # 等于mid_val的查询(直接处理) right_indices = [] # 大于mid_val的查询 for idx in query_indices: q = queries[idx] if q < mid_val: left_indices.append(idx) elif q == mid_val: result[idx] = mid # 找到匹配,设置索引 else: # q > mid_val right_indices.append(idx) # 递归处理左半部和右半部 helper(low, mid - 1, left_indices) helper(mid + 1, high, right_indices) # 初始调用:覆盖整个数组和所有查询索引 helper(0, len(arr) - 1, list(range(len(queries)))) return result # 示例测试 if __name__ == "__main__": arr = [1, 3, 5, 7, 9] # 排序数组 queries = [5, 2, 9] # 查询列表 print(binary_search_all(arr, queries)) # 输出:[2, -1, 4](索引从0开始) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值