POJ 3104 二分

题意

传送门 POJ 3104

这道题的教训是要考虑好复杂度和数据范围。

最先想到贪心法,优先队列每次处理当前未晾干衣服水分的最大值,TLE,因为极端情况 O ( m a x { a i } ) O(max\{a_{i}\})

考虑二分法, O ( n l o g ( m a x { a i } ) ) O(nlog(max\{a_{i}\})) ,搜索时间值,所有衣服都当做自然烘干叠加射线烘干(速度 K 1 K-1 )来处理,当水分大于自然烘干值,则必须使用射线,累加使用射线的次数(时间)即可。极端情况,射线次数累加值 i n t int 会溢出,需要使用 l o n g   l o n g long\ long 或者预处理。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_N 100005
using namespace std;
int N, K;
int A[MAX_N];

bool C(int t){
	int cnt = 0;
	for(int i = 0; i < N; i++){
		cnt += (A[i] - t <= 0 ? 0 : (A[i] - t - 1) / K + 1);
		if(cnt > t) return false;
	}
	return true;
}


int main(){
	while(~scanf("%d", &N)){
		for(int i = 0; i < N; i++) scanf("%d", A + i);
		scanf("%d", &K); --K;
		if(K == 0){
			printf("%d\n", *max_element(A, A + N));
			continue;
		}
		int left = 0, right = INF;
		while(right - left > 1){
			int mid = (left + right) >> 1;
			if(C(mid)) right = mid;
			else left = mid;
		}
		printf("%d\n", right);
	}
	return 0;
}
发布了91 篇原创文章 · 获赞 1 · 访问量 1609

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/105173915