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;
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bahuia/article/details/53780742
文章标签: stl set 二分
个人分类: STL 二分/三分
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭