题解 P2678 【跳石头】
alan20050721 · · 题解
本蒟蒻第一篇题解
首先说下本题思路:
1.看数据:显然n^2不可能,于是想到nlogn。
2.分析复杂度:logn肯定与排序,二分,堆有关,输入数据本来就有序,不用排序;堆,也用来做排序之类的工作,于是排除;所以用二分答案。
3.怎么验证:每次求当前石头与上一个有效的石头距离,然后与而二分数据比较看是否去掉,若去掉,计数器加一,最后再判断一下是否在要求范围内就可以了。
P.S: 坑点:题目中说的L是有用的,表示最后一个石头(终点)与起点的距离!!(我调了1个小时)
看代码吧:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <iomanip>
#include <algorithm>
#include <cstring> //本人不喜欢万能头文件。。
using namespace std;
int k, m, n, a[1000005];
inline int read() {
int ch = getchar();
while (ch > '9' || ch < '0')ch = getchar();
int num = ch - '0';
ch = getchar();
while (ch >= '0' && ch <= '9') {
num *= 10;
num += ch - '0';
ch = getchar();
}
return num;
} //快读是个好习惯
inline bool check(int x) { //贪心验证二分
int num = 0, now = 0; //num记录挪开石头数
for (register int i = 1; i <= n + 1; i++) {
if (a[i] - a[now] >= x)
now = i;
else //挪开
num++;
}
if (num <= m)return true;//判定是否符合标准
return false;
}
int main() {
k = read();
n = read();
m = read();
for (register int i = 1; i <= n; i++) {
a[i] = read();
}//读入数据
a[n + 1] = k; //终点石头也要算!!
int l = 0, r = k, mid, ans;//ans为答案
while (l <= r) { //二分答案
mid = (l + r) / 2;
if (check(mid) == true) {
l = mid + 1;
ans = mid;
}
else
r = mid - 1;
}
cout << ans << endl;
return 0;
}
管理大大求过!!