set codeforces567D One-Dimensional Battle Ships

来源:互联网 发布:淘宝卖家登入 编辑:程序博客网 时间:2024/05/20 18:44

题意:有一个长度为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;}


0 0
原创粉丝点击