codeforces 567D.One-Dimensional Battle Ships 解题报告

题目链接:http://codeforces.com/problemset/problem/567/D

题目意思:给出 1 * n 的 field,编号从左至右依次为 1,2,...,n。问射 m 枪之后(第 i 次射中编号 xi,则 xi 这一点是不能放置船只的!),能不能将 k 只 1 * a 的小船放到这些没有经过被射中编号的 field 中 。由于Alice 每次 shoot 的时候都会说 miss 的,即没有打中,你需要判断第几次shoot 使得整个field 不能放置 k 只 小船,如果都能放,最终输出 - 1.

  首先,外国人的题解真是好严谨,又好体~~~

  有几点需要解释下。事实上这几点也困惑了我好久 0.0

  (1)一开始整个区间 (n+1)/(a+1) 可能好多人还是不太明白。那么列条方程帮助理解吧。假设在[1, n] 中最多可以放置 x 只船,可以列出 x * a + (x - 1) = n,于是经若干合并同类项,就可以得到 x =  (n+1)/(a+1)。或者可以按题解者那样理解,由于最大放船数肯定是从最边边开始放的啦,然后间隔一个shoot之后随之放入另一只船。。。很容易知道,每只船占的空间至少为a+1(最尾那只可能不止又或者是a(可喜可贺啊)),那么我们可以虚拟多一个编号为 n+1 的 field。所以整个长度就为 (n+1)/ (a+1)了,很神奇哇~

  (2)(r-l+2)/(a+1) 是啥来的?!如果理解了第一点就很容易明白了。我们shoot完之后,这个 shoot 将空间一分为二了,选定的空间我们用集合set 的 upper_bound来找,返回的是 r ,前一个就是  l 。r-l+1很容易理解(不理解可以私聊我),再+1 就是虚拟的那个field。第(1)点已经说了,紧挨着边放置是最优解的条件!最后记得把shoot这个编号放入下一轮备选空间上。

  (3)空间中为什么要减完再加。因为有个shoot将空间一分为二嘛~~这个时候可以放置的船已经不是原来的[l, r] 这么多了。而是被分开的左区间[l, x-1] 和 [x+1, r] 之和这么多。

  

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <set>
 6 using namespace std;
 7
 8 set<int> s;
 9
10 int main()
11 {
12     #ifndef ONLINE_JUDGE
13         freopen("in.txt", "r", stdin);
14     #endif // ONLINE_JUDGE
15
16     int m, n, a, k, x;
17     while (scanf("%d%d%d", &n, &k, &a) != EOF) {
18         scanf("%d", &m);
19         s.clear();
20         s.insert(0), s.insert(n+1);   // 实现虚拟长度的小技巧
21         int sum = (n+1) / (a+1);
22         int ans = -1, f = 0;
23         for (int i = 1; i <= m; i++) {
24             scanf("%d", &x);
25             set<int>::iterator it = s.upper_bound(x);
26             int r = *it;
27             int l = *(--it);
28             sum = sum - (r-l)/(a+1) +(x-l)/(a+1) + (r-x)/(a+1);
29
30             if (sum < k && !f) {
31                 ans = i;
32                 f = 1;
33             }
34             s.insert(x);
35         }
36         printf("%d\n", ans);
37     }
38     return 0;
39 }

  

  

时间: 2024-08-10 18:00:14

codeforces 567D.One-Dimensional Battle Ships 解题报告的相关文章

codeforces 505A. Mr. Kitayuta&#39;s Gift 解题报告

题目链接:http://codeforces.com/problemset/problem/505/A 题目意思:给出一个长度不大于10的小写英文字符串 s,问是否能通过在字符串的某个位置插入一个字母,使得新得到的字符串成为回文串. /**************************************(又到自我反省时刻) 做的时候,通过添加一个单位使得长度增加1,找出中点,检验前一半的位置,找出对称位置替换成对应的前一半位置的字符,然后原字符串剩下的部分追加到后面,再判断回文.但是由于

Codeforces 130A - Testing Pants for Sadness(解题报告)

Testing Pants for SadnessCrawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 103A Description The average miner Vaganych took refresher courses. As soo

codeforces 499A.Inna and Pink Pony 解题报告

题目链接:http://codeforces.com/problemset/problem/499/A 题目意思:有两种按钮:1.如果当前观看的时间是 t,player 可以自动处理下一分钟,姑且理解为跳到t+1:  2.直接跳过 x 分钟,如果player在第 t 分钟,则可以跳到 t+x.问恰好可以看完 n 部电影的最少观看时间.观看一部电影表示 li, li+1, li+2, ..., ri-1, ri 的时间都要覆盖到. 一开始做的时候想得太简单了,确实需要每部电影的所有时间,但是如果不

codeforces 510B. Fox And Two Dots 解题报告

题目链接:http://codeforces.com/problemset/problem/510/B 题目意思:给出 n 行 m 列只有大写字母组成的字符串.问具有相同字母的能否组成一个环. 很容易知道要用到深搜.暴力搜索--- 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 cons

codeforces 556B. Case of Fake Numbers 解题报告

题目链接:http://codeforces.com/problemset/problem/556/B 题目意思:给出 n 个齿轮,每个齿轮有 n 个 teeth,逆时针排列,编号为0 ~ n-1.每按一次 button,每个齿轮都会有且仅有一个活动的tooth,对于偶数编号的齿轮,它下一个活动tooth是紧挨着当前tooth的逆时针方向的那个:而奇数编号的齿轮,下一个活动tooth是顺时针的那个.给出每个齿轮的活动tooth,问通过按下有限次的button,问能不能得到一个0,1,...,n-

CodeForces 501B(STL_H题)解题报告

题目链接:http://codeforces.com/problemset/problem/501/B -------------------------------------------------------------------------------- 题意:N个改名操作,要求输出最开始和最终的名字 思路:利用map的操作,读取输入之后,查找是否在key中,如果不在key中,建立新的关系.如果在key中,建立新的key-value对,擦除旧的key-value对.最终通过迭代器输出k

CodeForces 915C(DFS_E题)解题报告

题目链接:http://codeforces.com/problemset/problem/915/C --------------------------------------------------------------------------------- 题意:给你两个数 a和 b,可以打乱 a每位数的顺序,让你求满足 小于等于b 的最大值.. 思路:首先,观察到数值比较大,所以采用字符串读入的方式进行处理,通过比较字典序,交换不同位数是的保证每一次操作都是最优解. 代码: #inc

CodeForces 689B(BFS_B题)解题报告

题目链接:http://codeforces.com/problemset/problem/689/B -------------------------------------------------------------------------------- 题意:在一条直线上有n个城市,相邻两个城市之间的花费为1,但是有捷径,可以到捷径所在的点,而且只需要1的花费,捷径不能前往之前的城市. 思路:经典的,bfs打板直接过.唯一要注意的是这种情况,如4-7有捷径,所以有可能到6的最短路径为

[Codeforces Round #194 (Div. 2)] Secret 解题报告 (数学)

题目链接:http://codeforces.com/problemset/problem/334/C 题目: 题目大意: 给定数字n,要求构建一个数列使得数列的每一个元素的值都是3的次方,数列之和S大于n,且删掉数列中的任意一个元素数列之和都会小于n,最小化这个数列的长度 题解: 我们考虑从小到大枚举k,取最小的k,使得,答案就是$n/3^k+1$ 为什么呢? 我们考虑一个合法的数列,其中最小的元素是A,那么S一定是A的倍数.假设n是A的倍数,又S>n,那么S-A>=n,这样的话去掉A这个数