• Codeforces Round #476 (Div. 2)——D. Single-use Stones(二分做法)


    Codeforces Round #476 (Div. 2)——D. Single-use Stones(二分做法)

    Problem - 965D - Codeforces

    A lot of frogs want to cross a river. A river is ww units width, but frogs can only jump l units long, where l

    The stones are located at integer distances from the banks. There are aiai stones at the distance of i units from the bank the frogs are currently at. Each stone can only be used once by one frog, after that it drowns in the water.

    What is the maximum number of frogs that can cross the river, given that then can only jump on the stones?

    Input

    The first line contains two integers ww and l (1≤l

    The second line contains w−1 integers a1,a2,…,aw−1 (0≤ai≤10^4), where aiai is the number of stones at the distance ii from the bank the frogs are currently at.

    Output

    Print a single integer — the maximum number of frogs that can cross the river.

    Examples
    input
    10 5
    0 0 1 0 2 0 0 1 0
    
    • 1
    • 2
    output
    3
    
    • 1

    问题解析

    看了别的题解都是什么最大流最小割,咱比较笨不理解,转而学习了一下二分的写法。

    很容易想到如果mid个青蛙能过河,mid-1肯定也可以,mid+1不一定可以,满足二分性。

    至于check函数:

    1. 用双端队列模拟,双端队列存储的是所有青蛙的位置(first)以及这个位置的青蛙个数(second),因为初始青蛙都在位置0,而我们枚举的青蛙数是mid,所以初始队列插入一个{0,mid}。
    2. 遍历数组,当a[i]不为0时,说明有石头,我们从队首取出青蛙放在这个石头上,直到石头放不下青蛙了,或者之前的青蛙全部被放在这个石头上,然后我们再把这个石头的位置和所放青蛙数存入队尾。
    3. 要注意,如果当前位置与队首位置相差距离大于l了,说明当前队首的青蛙是到不了尾部的,因为现在已经到了他们跳不到的地方,而他们还没被放在别的石头,那么他们就只能留在那个石头上那也去不了,既然有一部分去不了队尾,说明我们当前枚举的青蛙数mid是不可行的,返回false。
    4. 最后,判断一下队首的青蛙下标到末尾w的距离是否小于等于l(即队首的青蛙是否能一下子跳到岸上),如果不行,同理3,返回false。如果可以,注意,我们队列首到队列尾存的青蛙位置是逐步接近w的,如果队首的都能跳到岸上,剩下的也行,返回true。

    AC代码

    const int N = 1e6 + 50;
     
    int a[N], n, l;
    bool check(int mid)
    {
        dequeque;
        que.push_back({ 0,mid });
        for (int i = 1; i < n; i++)
        {
            if (a[i] == 0)continue;
            if (i - que.front().first > l)return 0;
            int x = 0;
            while (!que.empty() && x < a[i])
            {
                auto ans = que.front();
                que.pop_front();
                if (x + ans.second <= a[i])x += ans.second;
                else
                {
                    ans.second -= (a[i] - x);
                    x = a[i];
                    que.push_front(ans);
                }
            }
            que.push_back({ i,x });
        }
        return n - que.front().first <= l;
    }
     
    void solve()
    {
        cin >> n >> l;
        for (int i = 1; i < n; i++)cin >> a[i];
        int l = 0, r = 1e9;
        while (l < r)
        {
            int mid = (l + r + 1) / 2;
            if (check(mid))l = mid;
            else r = mid - 1;
        }
        cout << l;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    守望者的逃离(附题解)
    java计算机毕业设计行星中小学教辅平台源码+数据库+系统+lw文档+mybatis+运行部署
    Lambda 表达式详解
    RestTemplate使用方法
    java毕业设计超市网站mybatis+源码+调试部署+系统+数据库+lw
    PixCake:让你的照片焕发新生的AI人像处理技术修图软件
    二叉查找树(BST)
    lv6 嵌入式开发-Flappy bird项目
    GBase 8s gcadmin之distribution命令解析
    【备份】A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS
  • 原文地址:https://blog.csdn.net/fnmdpnmsl/article/details/127702397