一维战舰,一道考区间的好题

题目来源: CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
 收藏
 关注

爱丽丝和鲍博喜欢玩一维战舰的游戏。他们在一行有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 }

 

 
posted @ 2017-08-10 11:17  只有你  阅读(169)  评论(0编辑  收藏  举报