1. 程式人生 > 其它 >Solution -「營業」「CF567D」One-Dimensional Battle Ships

Solution -「營業」「CF567D」One-Dimensional Battle Ships

題目大意 - 翻譯

Alice 和 Bob喜歡在 \(1\times n\) 的表格中玩戰艦遊戲。遊戲開始時,Alice 有 \(k\) 艘戰艦,每艘戰艦長度為 \(a\),她需要把這些戰艦不重疊且不相鄰地放在格子中(不允許有兩艘戰艦的格子存在公共邊)。但她並不會告訴 Bob 她放的位置。

接下來,Bob 會用 \(m\) 顆炮彈嘗試打中 Alice 的戰艦,每顆炮彈會選擇一個格子打擊。但由於 Alice 喜歡作弊,所以她不會告訴 Bob 什麼時候擊中了戰艦。請你幫助 Bob 判斷,在第幾次發射炮彈後,Alice 一定會有一艘戰艦被擊中。

分析

不難看出整個問題是具有單調性的,即炮彈打出的越多就越有可能達成“戰艦肯定被打到了”這一成就。那麼就直接考慮 二分答案

當我們列舉到一個 mid 的時候,我們將所有在 mid 之前發射的炮彈對應到原表格上。得到的效果即原表格被分成了很多個區間。

在這樣的情況下如果我們考慮每一個區間的左端都被戰艦佔據(或不被佔),且右端一定不被佔據。則這樣的放置方法一定是合法的,且對於每一個區間,最多可以放 \(\frac{r - l}{a + 1}\) 艘戰艦。

那麼就可以求到在 mid 之前的所有炮彈打出的情況下,最多能保證多少戰艦不被打到。顯然如果這個個數小於 k ,這個答案就一定可以為最後答案。

當然因為我們要找的是最小的,所以在這個時候就繼續往小的找咯。

#include <cstdio>
#include <algorithm>
using namespace std; 

int Max(int x, int y) {return x > y ? x : y;}
int Min(int x, int y) {return x < y ? x : y;}
int Abs(int x) {return x < 0 ? -x : x;}

int read() {
    int k = 1, x = 0;
    char s = getchar();
    while (s < '0' || s > '9') {
        if (s == '-')
            k = -1;
        s = getchar();
    }
    while (s >= '0' && s <= '9') {
        x = (x << 3) + (x << 1) + s - '0';
        s = getchar();
    }
    return x * k;
}

void write(int x) {
    if(x < 0) {
    	putchar('-');
		x = -x;
    }
    if(x > 9)
		write(x / 10);
    putchar(x % 10 + '0');
}

void print(int x, char s) {
	write(x);
	putchar(s);
}

const int MAXN = 2e5 + 5;

struct node {
	int id, val;
	node() {}
	node(int Id, int Val) {
		id = Id;
		val = Val;
	}
} q[MAXN];

bool cmp(node x, node y) {
	return x.val < y.val;
}

int n, k, a, m;

bool check(int mid) {
	int ans = 0, last = 0;
	for(int i = 1; i <= m; i++) 
		if(q[i].id <= mid) {
			ans += ((q[i].val - last) / (a + 1));
			last = q[i].val;
		}
	ans += ((n - last + 1) / (a + 1));
	return ans < k;
}

int main() {
	n = read(), k = read(), a = read(), m = read();
	for(int i = 1; i <= m; i++) {
		q[i].val = read();	
		q[i].id = i;	
	}
	sort(q + 1, q + m + 1, cmp);
	int l = 1, r = m, res = -1;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if(check(mid)) {
			res = mid;
			r = mid - 1;
		}
		else
			l = mid + 1;
	}
	print(res, '\n');
	return 0;
}