1 条题解

  • 1
    @ 2023-10-20 0:08:37

    需要实现频繁的删除,我们考虑使用链表维护。且还牵扯到块的合并,所以对于每一个块维护一个块的链表。我们的两个链表长这个样子。

    image

    有了这样就好办了,每次取走一个水果就使用双向链表的删除操作即可。需要注意删除以后,我们要重新更新一下当前块的 bl,brb_l,b_r 这两个信息,

    image

    例如删去第一个块最左边黑色后, bl,brb_l,b_r 也要修改,如果这个块只有一个元素那么就不用管了,反正后续我们会重新合并块的信息。

    对于合并相同种类的块,我们对链表就正常往后跳,当跳到某一个节点后,当前节点和左边节点的值相同说明属于同一个水果,且当前节点是当前块的起点,说明这两个块需要合并,那我们就修改块链表的信息

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 2e5 + 5;
    int n, a[N];
    int l[N], r[N], bl[N], br[N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        a[0] = a[n + 1] = -1;// 设为 -1 避免和第一个比较
        r[0] = 1, l[n + 1] = n;
        for (int i = 1; i <= n; i++) l[i] = i - 1, r[i] = i + 1;
        for (int i = 1; i <= n; i++)//双指针求每一个块的范围 i ~ j
        {
            int j = i;
            while (j + 1 <= n && a[j + 1] == a[i]) j++;
            br[i] = j, bl[j] = i;
            i = j;
        }
        int tot = 0;
        while (tot < n)
        {
            for (int i = r[0]; i != n + 1; i = r[i])
            {
                tot++;
                cout << i << " ";
                int u = l[i], v = r[i]; // u是i的左边点编号,v是右边点编号
                r[u] = v, l[v] = u; // 删掉点 i 
                if (a[v] == a[i]) // 修改块的链表
                {
                    br[v] = br[i], bl[br[i]] = v;
                }
                i = br[i]; //先跳到块的末尾,循环结束后i = r[i] 去往下一个块
            }
            cout << "\n";
            for (int i = r[0]; i != n + 1; i = r[i])
            {
                if (a[i] == a[l[i]] && bl[br[i]] == i)
    //当前点 a[i] 和左边节点值相同,且当前点是块的起点,块的起点是如何判断的?
    //首先 br[i] 可以获取到块的终点,然后终点的左连接bl[块终点] 等于 i 本身说明 i 为块起点
                {
                    int ed = l[i]; // 上一个块的终点
                    int st = i; // 当前块的起点
                    br[bl[ed]] = br[st];
                    bl[br[st]] = bl[ed];
                }
                i = br[i];//先跳到块的末尾,循环结束后i = r[i] 去往下一个块
            }
            
        }
        return 0;
    }
    
    • 1

    [普及~提高][CSP-J 2021] 小熊的果篮

    信息

    ID
    1357
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    272
    已通过
    102
    上传者