当前位置: 代码迷 >> 综合 >> set codeforces567D One-Dimensional Battle Ships
  详细解决方案

set codeforces567D One-Dimensional Battle Ships

热度:19   发布时间:2023-12-14 04:00:47.0

题意:有一个长度为n的区间,现在有k个长度为a的东西,放在长度为n的区间上,且这k个东西没有重叠或接触的地方,也就是两两直接至少中间隔了一个空位

现在Bob按顺序选择了许多个点,Bob每选择一个点,Alice都会撒谎说这个点没有被覆盖,问,Bob在选了哪些点后,能确定Alice一定在说谎,也就是,在第几个点的时候,可以确定这个点一定被覆盖了


思路:

ans记录上一次中区间内最多能放多少个长度为a的东西

每次询问一个点t的时候,找到最左边已经查询过的点记为L,和最右边已经查询过的点记为R,这可以用set来维护。

然后算出这[L+1,R-1]里面本身最多能放多少个长度为a的东西,因为我t点必须是空位,先拿ans-solve(L+1,R-1),就得到了如果[1,L-1]和[R+1,n]能放多少个长度为a的东西的数量

然后再加上[L+1,t-1]和[t+1,R-1],也就是将以前的一个连续区间分成两部分以后,分别能放多少个,,这样就更新了ans

以后每次只要比较ans和k的大小关系,,就能得到答案了

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<iostream>
#include<functional>
#include<algorithm>using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int MX = 2e5 + 5;
const int INF = 0x3f3f3f3f;int n, k, a, m, t;
int A[MX];int solve(int L, int R) {if(L > R) return 0;return (R - L + 2) / (a + 1);
}int main() {//freopen("input.txt", "r", stdin);scanf("%d%d%d%d", &n, &k, &a, &m);set<int>work;work.insert(0);work.insert(n+1);int ans = -1, sum = solve(1, n);for(int i = 1; i <= m; i++) {scanf("%d", &A[i]);}for(int i = 1; i <= m; i++) {t = A[i];int L = *(--work.lower_bound(t));int R = *work.upper_bound(t);work.insert(t);sum = sum - solve(L + 1, R - 1) + solve(L + 1, t - 1) + solve(t + 1, R - 1);if(sum < k) {ans = i;break;}}printf("%d\n", ans);return 0;
}


  相关解决方案