Codeforces 567D One-Dimensional Battle Ships

传送门

D. One-Dimensional Battle Ships
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Alice and Bob love playing one-dimensional battle ships. They play on the field in the form of a line consisting of n square cells (that is, on a 1 × n table).

At the beginning of the game Alice puts k ships on the field without telling their positions to Bob. Each ship looks as a 1 × a rectangle (that is, it occupies a sequence of a consecutive squares of the field). The ships cannot intersect and even touch each other.

After that Bob makes a sequence of "shots". He names cells of the field and Alice either says that the cell is empty ("miss"), or that the cell belongs to some ship ("hit").

But here's the problem! Alice like to cheat. May be that is why she responds to each Bob's move with a "miss".

Help Bob catch Alice cheating — find Bob's first move, such that after it you can be sure that Alice cheated.

Input

The first line of the input contains three integers: nk and a (1 ≤ n, k, a ≤ 2·105) — the size of the field, the number of the ships and the size of each ship. It is guaranteed that the nk and a are such that you can putk ships of size a on the field, so that no two ships intersect or touch each other.

The second line contains integer m (1 ≤ m ≤ n) — the number of Bob's moves.

The third line contains m distinct integers x1, x2, ..., xm, where xi is the number of the cell where Bob made the i-th shot. The cells are numbered from left to right from 1 to n.

Output

Print a single integer — the number of such Bob's first move, after which you can be sure that Alice lied. Bob's moves are numbered from 1 to m in the order the were made. If the sought move doesn't exist, then print "-1".

Sample test(s)
input
11 3 3
5
4 8 6 1 11
output
3
input
5 1 3
2
1 5
output
-1
input
5 1 3
1
3
output

1

--------------------------------------------------------------------------------------------------

比赛时很快想到解法,之后意识到要用线段树维护,但我对线段树还不是特别熟练,没写出来,想想十分可惜。

Solution

任意时刻Alice可以放置ship的地方是一些区间(线段)(active segments),我们设法维护这些区间,需支持下列操作:

1. 查询某个cell所在的区间

2. 将某个区间分成多个区间

根据Bob每次guess的结果维护Alice的active segments,计算出Alice当前最多能放几个ship,若果小于k,则可断言Alice说谎了。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include<bits/stdc++.h>
using namespace std;
const int MAX_N=2e5+10;
int tag[MAX_N<<2];
int ma[MAX_N<<2];
typedef pair<int,int> P;
P query(int id, int L, int R, int val){
	if(tag[id]) return P(L, tag[id]);
	int mid=(L+R)>>1;
	if(ma[id<<1]>=val)
		return query(id<<1, L, mid, val);
	return query(id<<1|1, mid+1, R, val);
}
void insert(int id, int L, int R, int l, int r, int val){
	if(l>r) return;
	if(l<=L&&R<=r) tag[id]=ma[id]=val;
	else{
		int ls=id<<1, rs=ls|1, mid=(L+R)>>1;
		if(tag[id]){
			tag[ls]=ma[rs]=tag[id];	//error-prone
			tag[rs]=ma[rs]=tag[id];
			tag[id]=0;
		}
		if(l<=mid)
			insert(ls, L, mid, l, r, val);
		if(r>mid)
			insert(rs, mid+1, R, l, r, val);
		ma[id]=max(ma[ls], ma[rs]);
	}
}
int n, k, a, m, g, now;
int cap(int len){return (len+1)/(a+1);}
void init(){
	scanf("%d%d%d%d", &n, &k, &a, &m);
	tag[1]=ma[1]=n;
	now=cap(n);
}
#define X first
#define Y second
int main(){
	freopen("in", "r", stdin);
	init();
	P seg;
	int ans=-1;
	for(int i=1; i<=m; i++){
		scanf("%d", &g);
		//printf("g: %d\n", g);
		seg=query(1, 1, n, g);
		//printf("%d %d\n", seg.X, seg.Y);
		now-=cap(seg.Y-seg.X+1);
		now+=cap(g-seg.X);
		now+=cap(seg.Y-g);
		//printf("%d\n", now);
		if(now<k){
			ans=i;
			break;
		}
		insert(1, 1, n, seg.X, g-1, g-1);
		insert(1, 1, n, g, g, g);
	}
	printf("%d\n", ans);
}

 P.S. 这道题再次写复杂了,我的解法是一种模拟解法,线段树只是起到加速的作用,并不是算法的核心。

我的算法是:模拟Bob的猜测过程,每猜一次就判断当前能否放得下k条船。但如果裸模拟的话可能会T。

这道题比较简单的解法是二分答案,然后再O(n)判断。

当时我完全没想到可O(n)判断,当然也没想到二分答案(这可是赤裸裸的二分答案题啊),

二分答案的复杂度是严格的O(n log m),我的写法的复杂度还依赖于答案的大小,最坏情况复杂度是O(m log n)。

——————————————————————————————————————————————————————

现在头脑越来越不灵了T^T。

posted @ 2015-08-07 04:04  Pat  阅读(370)  评论(0编辑  收藏  举报