描述
题解
好长时间没有见过51更新4级以下的题了,今天多了一道从CF上抓来的题,很有趣,区间问题,对于我这种做题少的人来说是一种区间新题型。
比较简单的是直接上STL的set
,用二分搞搞(代码One)。但是这个耗时贼高,于是发现这道题不用set
和二分也是完全可以的(代码Two),利用一维数组从某一出发点向两边查找,其实问题的关键是如何求一段区间能放下多少艘战舰,很明显:
num = (len + 1) / (a + 1);
这样也就没啥问题了。
代码
One:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <set>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = 2e5 + 10;
set<int> s;
set<int>::iterator it;
set<int>::iterator it_;
int vis[MAXN];
int main(int argc, const char * argv[])
{
int n, k, a;
cin >> n >> k >> a;
int m;
cin >> m;
int maxNum = (n + 1) / (a + 1); // 初始化最多可以放maxNum艘
s.insert(0); // 下界
s.insert(n + 1); // 上界
mem(vis, 0);
int point;
for (int i = 0; i < m; i++)
{
scanf("%d", &point);
if (vis[point])
{
continue;
}
vis[point] = 1;
s.insert(point);
it = s.lower_bound(point);
it--;
it_ = s.upper_bound(point);
maxNum -= ((*it_) - (*it)) / (a + 1) - ((*it_) - point) / (a + 1) - (point - (*it)) / (a + 1);
if (maxNum < k)
{
printf("%d\n", i + 1);
return 0;
}
}
printf("-1\n");
return 0;
}
Two:
#include <stdio.h>
const int MAXN = 2e5 + 10;
int place[MAXN];
int main()
{
int n, k, a;
scanf("%d%d%d", &n, &k, &a);
int m;
scanf("%d", &m);
int flag = -1;
int left, right;
int maxNum = (n + 1) / (a + 1);
int x;
for (int i = 0; i < m; i++)
{
scanf("%d", &x);
place[x] = 1;
for (left = x - 1; left >= 1 && place[left] == 0; left--) ;
for (right = x + 1; right <= n && place[right] == 0; right++) ;
maxNum -= (right - left) / (a + 1) - (right - x) / (a + 1) - (x - left) / (a + 1);
if (maxNum < k && flag == -1)
{
flag = i + 1;
break;
}
}
printf("%d\n", flag);
return 0;
}