题目链接:
一行有n个方格的纸上,爱丽丝放k个战舰在这个表格中,并不把具***置告诉鲍博。每一只战舰的形状是 1×a 的长方形(也就是说,战舰会占据a个连续的方格)。这些战舰不能相互重叠,也不能相接触。然后鲍博会做一系列的点名。当他点到某个格子的时候,爱丽丝会告诉他那个格子是否被某只战舰占据。如果是,就说hit,否则就说miss。但是这儿有一个问题!爱丽丝喜欢撒谎。他每次都会告诉鲍博miss。请你帮助鲍博证明爱丽丝撒谎了,请找出哪一步之后爱丽丝肯定撒谎了。如果不能证明输出-1。
第一行有三个整数n,k和a。
第二行是一个整数m(1≤m≤n),表示鲍博的点名次数。
第三行有m个不同的整数x1,x2,…,xm,xi是鲍博第i次点名的格子编号。格子从左到右按照1到n编号。

思路:这道题当时想的是计算浪费的空间,当浪费的空间使得空间放不下战舰为止。但是计算过的区间要标记,但是战舰的位置不确定,所以区间无法标记。
然后也想了二分,计算能放下战舰的最大数量,当最大数量<k就证明爱丽丝撒谎了。但是也感觉无法维护。。。。。

看了题解,就是二分。。。。
因为每个战舰不能相接触,我们可以把每次询问x;相当在x空格插入一堵墙(开始插入0, n+1)。并把这个区间一分为二。ans=ans-之前这个区间能放下的最大数量+(左区间能放下的最大数量+右区间能放下的最大数量)

那么第一种思路也能维护浪费的空间:ans=ans-之前这个区间浪费的空间+(左区间浪费的空间+右区间浪费的空间)

思考:当时还在想是不是考虑这个区间是不是最左最右区间,因为这样可以可以放最左边或最右边。也考虑每次询问是否相同。该用multiset还是set。
后来引入墙就发现,每次询问都是同一种过程,而且询问相同就是在之前有墙的地方放墙,什么也没有改变。

#include <bits/stdc++.h>
using namespace std;

set<int> s;
int main()
{
    int n, k, a, m, ans;
    scanf("%d%d%d",&n,&k,&a);
    ans=(n+1)/(a+1);
    s.insert(0);
    s.insert(n+1);

    scanf("%d",&m);
    int p=0;
    for(int i=1;i<=m;i++)
    {
        int f, l, r;
        scanf("%d",&f);
        l=*(--s.lower_bound(f));//区间左边的墙
        r=*(s.upper_bound(f));//区间右边的墙
        ans-=(r-l)/(a+1);//减去之前这个区间能放下的最大数量
        ans+=(f-l)/(a+1)+(r-f)/(a+1);//加上左区间能放下的最大数量+右区间能放下的最大数量
        s.insert(f);//插入墙

        if(ans<k&&p==0)
        p=1, cout<<i<<endl;
    }
    if(!p)
        cout<<-1<<endl;

    return 0;
}