一维战舰,一道考区间的好题
收藏
关注
爱丽丝和鲍博喜欢玩一维战舰的游戏。他们在一行有n个方格的纸上玩这个游戏(也就是1×n的表格)。
在游戏开始的时候,爱丽丝放k个战舰在这个表格中,并不把具体位置告诉鲍博。每一只战舰的形状是 1×a 的长方形(也就是说,战舰会占据a个连续的方格)。这些战舰不能相互重叠,也不能相接触。
然后鲍博会做一系列的点名。当他点到某个格子的时候,爱丽丝会告诉他那个格子是否被某只战舰占据。如果是,就说hit,否则就说miss。
但是这儿有一个问题!爱丽丝喜欢撒谎。他每次都会告诉鲍博miss。
请你帮助鲍博证明爱丽丝撒谎了,请找出哪一步之后爱丽丝肯定撒谎了。
Input
单组测试数据。 第一行有三个整数n,k和a(1≤n,k,a≤2*10^5),表示表格的大小,战舰的数目,还有战舰的大小。输入的n,k,a保证是能够在1×n的表格中放入k只大小为a的战舰,并且他们之间不重叠也不接触。 第二行是一个整数m(1≤m≤n),表示鲍博的点名次数。 第三行有m个不同的整数x1,x2,...,xm,xi是鲍博第i次点名的格子编号。格子从左到右按照1到n编号。
Output
输出一个整数,表示最早一次能够证明爱丽丝一定撒谎的点名编号。如果不能证明,输出-1。点名的编号依次从1到m编号。
Input示例
样例1 11 3 3 5 4 8 6 1 11 样例2 5 1 3 2 1 5
Output示例
样例输出1 3 样例输出2 -1
分析
在区间【1,n】上最多能放(n+1)/(a+1)个战舰。如果某个空格没有战舰,相当于将一个区间分割成了两个区间,这样它能放的战舰数就会相应的减少((大区间能放的战舰数)-(小区间1能放的战舰数+小区间2能放的战舰数))个。
随着爱丽丝不断地报miss,区间不断地被分割。当最后一次分割使得能放的战舰数小于k个时,该分割不能进行,即爱丽丝撒慌。
代码
1 #include <iostream> 2 #include <set> 3 using namespace std; 4 int n,k,a; 5 int m; 6 set<int> s; 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 while(cin>>n>>k>>a) 11 { 12 s.clear(); 13 int flag=0; 14 int res=-1; 15 int ans=(n+1)/(a+1); 16 17 s.insert(0); 18 s.insert(n+1); 19 20 cin>>m; 21 for(int i=1;i<=m;i++) 22 { 23 int tmp; 24 cin>>tmp; 25 if(flag) continue; 26 27 s.insert(tmp); 28 set<int>::iterator ite=s.find(tmp); 29 int left=*--ite; 30 int right=*(++(++ite)); 31 ans-=(right-left)/(a+1)-(right-tmp)/(a+1)-(tmp-left)/(a+1); 32 33 if(ans<k) 34 flag=1,res=i; 35 } 36 37 cout<<res<<endl; 38 } 39 return 0; 40 }