代码改变世界

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

2017-08-11 10:48  tlnshuju  阅读(161)  评论(0编辑  收藏  举报

题目的意思是:

如今有一个长度为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!