Alice and Bob love playing one-dimensional battle ships. They play on the field in the form of a line consisting of nsquare 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 a1 × 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.
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 aon 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.
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".
11 3 3
5
4 8 6 1 11
3
5 1 3
2
1 5
-1
5 1 3
1
3
1
比赛的时候没搞出来,really sad.
其实这题很容易啊....
首先,对于lie 的判断应该基于能放的船的个数.
能放的船的个数是随着射的点数的增加而减少的.
射完每个点后更新能放的船的个数,如果这个时候已经无法放下k条船了,说明lie了.
如果所有都射完也没发生,那么就-1.
由于船与串不能相邻,除了最后一条船,每条船实际占的size 应该为a+1
那么很容易知道对于长度为l的区间,能放的船的个数为(l+1)/(a+1)
这是初始能放的船的个数,为最大值.
当射了点b之后,破坏的是b所在的一段最大的没有被射过点的区间的连续性.
做法是找到距离b点最近的左端和右端的被射过的点.
可以用set 搞,找的时候upper_bound
记得初始化的时候把 0点和 n+1 点当成射过的.
/************************************************************************* > File Name: code/cf/#314/D.cpp > Author: 111qqz > Email: rkz2013@126.com > Created Time: 2015年08月16日 星期日 00时27分54秒 ************************************************************************/ #include<iostream> #include<iomanip> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<map> #include<set> #include<queue> #include<vector> #include<stack> #define y0 abc111qqz #define y1 hust111qqz #define yn hez111qqz #define j1 cute111qqz #define tm crazy111qqz #define lr dying111qqz using namespace std; #define REP(i, n) for (int i=0;i<int(n);++i) typedef long long LL; typedef unsigned long long ULL; const int inf = 0x7fffffff; set<int> se; int n,k,a,m,b; set<int>::iterator it; int cal (int x,int y) //cal 函数计算出当射了b之后,因此减少的能放船的个数. { int res; res = (y-x)/(a+1)-(y-b)/(a+1)-(b-x)/(a+1);//由于射了b点,相当于之前连续的区间(x,y)被分成了(x,b)和(b,y) //(x,y)区间能放的船的数量由之前变成了被分成的两个小区间能放的船的数量的和. return res; } int main() { scanf("%d %d %d",&n,&k,&a); scanf("%d",&m); se.clear(); int sum=(n+1)/(a+1); //sum表示的是当前能放的船的个数 //容易知道,对于长度为l的点,最多能放的船的数量为(l+1)/(a+1); se.insert(0); se.insert(n+1);//由于要找要被射的点两遍最近的被射的点,我们不妨认为0点和n+1点也是被射的,这样处理断点容易些. int ans = -1; bool flag = false; for (int i=1;i<=m;i++) { scanf("%d",&b); if (flag) continue; it=se.upper_bound(b); int y=*it; int x=*(--it); //y和x分别是离b点最近且已经被射的点 sum = sum - cal(x,y); if (sum<k) { ans = i; flag = true; } se.insert(b); } cout<<ans<<endl; return 0; }