您的位置:首页 > 其它

Codeforces Round #Pi (Div. 2) —— D One-Dimensional Battle Ships

2015-08-08 00:37 337 查看
题目的意思是:

现在有一个长度为n,宽为1的方格,在上面可以放大小为1*a船,然后输入为n,k,a;分别为平地的大小,船的数量,船的长度。

一个叫alice的人已经在地图上摆好了船的位置。

然后bob总共可以有m次攻击的机会,然后他每次攻击的点为xi,但是alice并不会告诉它有没有打中(也就是说每次都认为他是miss的),问你,bob可以在第几次攻击的时候推测出alice在撒谎,如果推测不出来则输出-1.

这里每两条相邻的船不能相互接壤。

思路:

用set来维护每一段的区间。

首先,我们最多可以放sum=(n+1)/(a+1)条船。

这个公式是怎么来的呢? 我们可以这样想: 因为船不能接壤,所以当有k条船时,n最少为k*(a+1)-1; 然后反解就能得到答案了。

然后我们每次攻击一个点t,就相当于把线段从中间隔开来了,我们要找到离点t最近的左右端点t1,t2,因为它们中间还插了一个t,所以就相当于t1,t2被分割开来了。

然后当前船的数量可以由另一个公式得到: sum=sum-(t2-t1)/(a+1)+(t-t1)/(a+1)+(t2-t)/(a+1) ;这里的意思就相当于把原先的那个区间的部分减掉,然后再加上后来分开来后的区间所能容纳的船的最大数目。

当sum<k的时候,就说明此时alice在撒谎。

这里查找左右端点用的是二分查找。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define me rng_58
#define maxn 200055
set<int> st;
set<int>::iterator it;
int main(){
	int n,k,a,m,i;
	scanf("%d%d%d",&n,&k,&a);
	scanf("%d",&m);
	st.insert(0); 
	st.insert(n+1);
	int sum=(n+1)/(a+1);
	int ans=-1;
	for(i=1;i<=m;i++){
		int t;
		scanf("%d",&t);
		it=st.upper_bound(t);
		int t1=*it;
		it--;				//这里为什么能减,学c++后再解答;
		int t2=*it;
		st.insert(t);		//这里只要把t压进去就好啦!!!小心!!! 
		sum=sum-(t1-t2)/(a+1)+(t-t2)/(a+1)+(t1-t)/(a+1);
		if(sum<k){
			ans=i;
			break;
		}
	}
	printf("%d\n",ans);
}
/*
5000 1660 2
20
1 100 18 102 300 81 19 25 44 88 1337 4999 1054 1203 91 16 164 914 1419 1487
*/


佩服那些能够想出来的人。Wish I can become the same like U one day!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: