One-Dimensional Battle Ships CodeForces - 567D (二分做法+解释)

One-Dimensional Battle Ships

CodeForces - 567D

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: n, k 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 n, k and a are such that you can put k 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".

Example
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

船           船          船           船

code：

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 200100
#define INF 0x3f3f3f3f
using namespace std;
int n,k,a,m;
int x[MAXN],x2[MAXN];
int check(int times){//解这道题的关键就在于这个check函数
int i;
for(i = 1; i <= times; i++){//把前times次的轰炸位置暂存下来
x2[i] = x[i];
}
sort(x2+1,x2+times+1);//排好序，这样从头往后遍历被分成的部分
int l = 1,tot = 0;
for(i = 1; i <= times; i++){
//这里需要花时间解释一下，因为这里我也好久才明白。根据前面解释在长度为n的长度内
//可以放置的船的条数是（n+1）/（a+1），n是实际的放置长度而+1是虚的只是我们故意多出1，这样整除出结果
//但是问题是我将整个长度分成了连续的times+1个部分，如果每部分都加上虚的1，就把整体表变长了
//而我们还得有间隔，那么只好让每部分的末尾舍去1，这样对于中间的长度为nn的每部分，我们实际的放置
//长度是nn-1，而我们是从下标1开始记录，所以x2[i]-L恰好是L~x2[i]这段长度-1，然后根据公式实际长度是
//nn-1 = x2[i]-L,所以放置个数为x2[i]-L+1/(a+1),也就是下面代码的这样写的原因
int len = (x2[i]-l)+1;
tot += len/(a+1);
l = x2[i]+1;
}
//上面说的是中间部分，而对于最后一部分，因为最后一条船可以放在表尾边上，不需要空出一个1
//或者说我们可以假设后面多一个虚的1，这样的话，实际放置长度就应该是L~n的长度n-L+1，然后根据公式
//再加1除（a+1）得到最后一部分放置船的个数
tot += ((n-l+1)+1)/(a+1);
//最后求和比较
if(tot >= k)
return 1;
return 0;
}
int main(){
scanf("%d%d%d%d",&n,&k,&a,&m);
int i;
for(i = 1; i <= m; i++)
scanf("%d",&x[i]);
int l = 1,r = m,ans = INF;//边界
while(l<=r){//二分
int m=(l+r)/2;
if(check(m))//前面整体思路中已经解释，不在赘述
l = m+1;
else{
r = m-1;
ans = min(ans,m);
}
}
if(ans == INF)
ans = -1;
printf("%d\n",ans);
return 0;
}