51Nod - 1521 STL +二分

题意:

爱丽丝和鲍博喜欢玩一维战舰的游戏。他们在一行有n个方格的纸上玩这个游戏(也就是1×n的表格)。

在游戏开始的时候,爱丽丝放k个战舰在这个表格中,并不把具体位置告诉鲍博。每一只战舰的形状是 1×a 的长方形(也就是说,战舰会占据a个连续的方格)。这些战舰不能相互重叠,也不能相接触。

然后鲍博会做一系列的点名。当他点到某个格子的时候,爱丽丝会告诉他那个格子是否被某只战舰占据。如果是,就说hit,否则就说miss。

但是这儿有一个问题!爱丽丝喜欢撒谎。他每次都会告诉鲍博miss。

请你帮助鲍博证明爱丽丝撒谎了,请找出哪一步之后爱丽丝肯定撒谎了。

思路:

利用set保存各个miss点的位置,另外用cnt保存当前格子中最多能存放几个战舰,每次询问一个新的点pos,都利用二分找到这个点左右两边的第一个点l,r,这样就可以计算出增加了pos这个点前后cnt损失了多少,如果cnt < k了就输出当前询问编号,否则将pos也插入set。

一开始看错题了,没看到战舰也不能接触,所以一段长度为len的连续区间内最多能放(len+1)/(a+1)艘战舰。

代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;

int q[MAXN];
set <int> :: iterator it;

int main() {
    int n, m, k, a;
    scanf("%d%d%d%d", &n, &k, &a, &m);
    for (int i = 1; i <= m; i++)
        scanf("%d", &q[i]);
    set <int> st;
    int cnt = (n + 1) / (a + 1);
    st.insert(0); st.insert(n + 1);
    for (int i = 1; i <= m; i++) {
        if (st.find(q[i]) != st.end()) continue;
        it = st.upper_bound(q[i]);
        int r = *it, l = *(--it);
       // printf("%d %d\n", l, r);
        int t1 = (r - l) / (a + 1), t2 = (r - q[i]) / (a + 1) + (q[i] - l) / (a + 1);
        cnt -= (t1 - t2);
       // cout << cnt << endl;
        if (cnt < k) {
            printf("%d\n", i);
            return 0;
        }
        st.insert(q[i]);
    }
    puts("-1");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值