14116: 【原4116】刀位分配
题目
题目描述
author: 狐之助 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4116
Description
审神者最近得到了一大笔小判,用这些小判扩建了一下刀位(这些刀位从左到右排成一条直线,每个刀位在一个坐标点x上(0 <=x<=1,000,000,000),用来放她心爱的刀剑们。但是不知道为什么,最近发生了一件怪事。如果把两把刀放在一起,那么一到晚上,就会听到两个人说话的声音,这让还是一个小女孩的审神者觉得很害怕,于是她决定每个刀位只放一把刀,并且两把刀的间距越远越好。
已知审神者现在一共有N (2 <= N <= 100,000)个刀位和S (2 <= S <=N)把刀。她想给定一种放置刀剑的方法,使得每两把刀的最短距离越大越好。请写一个程序帮助这个小女孩,让她知道最大的最短距离是多少吧!
Input Format
第一行:两个用空格隔开的数字,分别代表N和C
第二到第N+1行:每行一个数字,代表刀位的坐标
Output Format
一个数字,代表最大的最短距离
Sample Input
5 3
1
2
8
4
9
Sample Output
3
Hint
审神者可以把这三把刀分别放在1,4,8的位置。
BugenZhao's solution
//
// Created by BugenZhao on 2019/3/23.
//
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
using ll=long long;
int n, s;
int *x;
bool check(int d) {
int count = 1, lastPos = 0;
for (int i = 1; i < n; ++i) {
if (x[i] - lastPos >= d) {
++count;
lastPos = x[i];
}
}
return count >= s;
}
int main() {
cin >> n >> s;
x = new int[n]{};
for (int i = 0; i < n; ++i) {
scanf("%d", x + i);
}
sort(x, x + n);
int tmp = x[0];
for (int i = 0; i < n; ++i) {
x[i] -= tmp;
}
int min = 0, mid, max = x[n - 1];
while (min <= max) {
mid = (min + max) / 2;
if (check(mid)) min = mid + 1;
else max = mid - 1;
}
cout << max << endl;
}
FineArtz's solution
/* 刀位分配 */
#include <iostream>
using namespace std;
int n, s;
int a[100005];
void qsort(int l, int r){
int i = l, j = r;
int mid = a[(i + j) / 2];
while (i <= j){
while (a[i] < mid)
++i;
while (a[j] > mid)
--j;
if (i <= j){
int t = a[i];
a[i] = a[j];
a[j] = t;
++i;
--j;
}
}
if (i < r)
qsort(i, r);
if (j > l)
qsort(l, j);
}
bool check(int ans){
int i = 1, j = 2, t = s - 1;
while (j <= n){
if (a[j] - a[i] >= ans){
--t;
i = j;
}
if (t == 0)
return true;
++j;
}
return false;
}
int main(){
cin >> n >> s;
for (int i = 1; i <= n; ++i)
cin >> a[i];
qsort(1, n);
int l = 1, r = a[n] - a[1], mid;
while (l < r){
mid = (l + r) / 2 + (l + r) % 2;
if (check(mid))
l = mid;
else
r = mid - 1;
}
cout << l << endl;
return 0;
}
ligongzzz's solution
#include "iostream"
using namespace std;
template <class T, class T_val = decltype(*declval<T>()),
class Compare = bool (*)(T_val, T_val)>
void quick_sort(T start, T end,
Compare cmp = [](T_val a, T_val b) {return a < b; }) {
if (start == end)
return;
auto i = start, j = end;
--j;
if (i == j)
return;
//交换
auto key = *start;
for (bool status = true; i != j;) {
if (status) {
if (cmp(*j, key)) {
*i = *j;
++i;
status = false;
}
else
--j;
}
else {
if (cmp(key, *i)) {
*j = *i;
--j;
status = true;
}
else
++i;
}
}
*i = key;
//递归
quick_sort(start, ++i, cmp);
quick_sort(i, end, cmp);
}
//记录被选中的点
int choose[100009] = { 0 };
int main() {
int n, m;
ios::sync_with_stdio(false);
cin >> n >> m;
int* dis = new int[n];
for (int i = 0; i < n; i++)
cin >> dis[i];
quick_sort(dis, dis + n);
int cl = 0, cr = dis[n - 1], ans = 0;
//二分法
while (cl <= cr) {
int mid = (cl + cr) >> 1, cnt = 0;
for (int i = 1, startNum = 0; i < n; i++)
if (dis[i] - dis[startNum] < mid) cnt++;
else startNum = i;
if (cnt > n - m) cr = mid - 1;
else {
cl = mid + 1;
ans = mid;
}
}
cout << ans;
return 0;
}
q4x3's solution
/**
* 排序 + 二分
**/
#include <iostream>
#include <stdio.h>
using namespace std;
template <typename T>
void merge(int lo, int mi, int hi, T* a)
{
T* A = a + lo;
int lb = mi - lo;
T* B = new T[lb];
T* BB = B;
for(int i = 0;i < lb;++ i)
B[i] = A[i];
int lc = hi - mi;
T* C = a + mi;
int cnt = 0;
while(1) {
if ((lb == 0) && (lc == 0)) break;
if (lb == 0) {
A[cnt] = C[0];
++ cnt; ++ C; -- lc;
}
else if (lc == 0) {
A[cnt] = B[0];
++ cnt; ++ B; --lb;
}
else {
if(B[0] < C[0]) {
A[cnt] = B[0];
++ cnt; ++ B; -- lb;
}
else {
A[cnt] = C[0];
++ cnt; ++ C; -- lc;
}
}
}
delete []BB;
}
template <typename T>
void mergeSort(int lo, int hi, T* A)
{
if(hi - lo < 2) return;
int mi = (lo + hi) / 2;
mergeSort(lo, mi, A); mergeSort(mi, hi, A);
merge(lo, mi, hi, A);
}
int N, C, pos[100233];
bool check(int dis) {
int cnt = 1, cur = 0;
for(int i = 1; i < N;++ i) {
if(pos[i] - pos[cur] >= dis) {
++ cnt;
cur = i;
if(cnt >= C) return 1;
}
}
return 0;
}
int main() {
scanf("%d%d", &N, &C);
for(int i = 0;i < N;++ i) {
scanf("%d", &pos[i]);
}
mergeSort(0, N, pos);
int lo = 0, hi = 1e9 + 10;
while(lo <= hi) {
int mi = (lo + hi) / 2;
if(check(mi)) {
lo = mi + 1;
} else {
hi = mi - 1;
}
}
cout << lo << endl;
}
skyzh's solution
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
int L = 0, R = 1e9 + 2;
int pos[100000];
int N, S;
scanf("%d%d", &N, &S);
for (int i = 0; i < N; i++) scanf("%d", &pos[i]);
int M = 0;
sort(pos, pos + N);
while (L < R) {
M = (L + R + 1) / 2;
int next_pos = 0, s = 0;
for (int i = 0; i < N; i++) {
if (pos[i] >= next_pos) {
++s;
next_pos = pos[i] + M;
}
}
if (s >= S) L = M;
else R = M - 1;
}
printf("%d\n", L);
return 0;
}
victrid's solution
#include <cstring>
#include <iostream>
using namespace std;
//binary answer
int* MergeSort(int* list, int listSize) {
if (listSize == 1)
return list;
if (listSize == 2) {
if (list[0] > list[1]) {
int temp = list[0];
list[0] = list[1];
list[1] = temp;
return list;
}
return list;
}
int* tmplist = new int[listSize];
int* llst = MergeSort(list, listSize / 2);
int* rlst = MergeSort(list + listSize / 2, listSize - listSize / 2);
int lct = 0, rct = 0;
while (lct + rct != listSize) {
if ((llst[lct] <= rlst[rct] && lct < listSize / 2) || rct >= listSize - listSize / 2) {
tmplist[lct + rct] = llst[lct];
lct++;
} else {
tmplist[lct + rct] = rlst[rct];
rct++;
}
}
memcpy(list, tmplist, sizeof(int) * listSize);
delete[] tmplist;
return list;
}
int place[100000], place_count, knife_count;
bool check(int mind) {
int i = 0, total = 0;
for (int j = 0; j < place_count; j++) {
if (place[j] - place[i] >= mind) {
i = j;
total++;
if (total == knife_count - 1)
return 1;
}
}
return 0;
};
int main() {
cin >> place_count >> knife_count;
for (int i = place_count; i > 0; i--) {
scanf("%d", place + i - 1);
}
MergeSort(place, place_count);
int l = 0,
r = place[place_count - 1];
while (l < r) {
if (check((l + r + 1) / 2))
l = (l + r + 1) / 2;
else
r = (l + r - 1) / 2;
}
cout << l;
return 0;
}
yyong119's solution
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 100010;
int pos[MAX_N];
int n, s;
int main() {
scanf("%d%d", &n, &s);
for (int i = 0; i < n; ++i) scanf("%d", &pos[i]);
sort(pos, pos + n);
int l = 1, r = 1000000000;
while (l < r - 3) {
int mid = (l + r) >> 1, cnt = 1, p = 0, flag = 0;
for (int i = 1; i < n; ++i)
if (pos[i] - pos[p] >= mid) {
++cnt; p = i;
if (cnt >= s) {
flag = 1; break;
}
}
if (flag) l = mid;
else r = mid - 1;
}
int k;
for (k = r; k >= l; --k) {
int cnt = 1, p = 0;
for (int i = 1; i < n; ++i)
if (pos[i] - pos[p] >= k) {
++cnt; p = i;
}
if (cnt >= s) break;
}
printf("%d\n", k);
return 0;
}