zoukankan      html  css  js  c++  java
  • [CF1404C] Fixed Point Removal

    [CF1404C] Fixed Point Removal - 离线处理,线段树上二分

    Description

    给定一个含有 (n) 个正整数的序列 (a) ,对于一次操作,你可以任选一个位置 (i) 且满足 (a_i=i) ,那么就可以移除这个元素,并将后面所有的元素向前移动一位。对于每个相互独立的询问 (x,y) 需要你求出在前 (x) 个元素以及后 (y) 个元素不能被移除的情况下,最多可以进行几次操作。(n,q leq 3 imes 10^5)

    Solution

    对每个位置的元素,线段树维护它在整个过程中的 (i-a_i),一个元素显然只有在 (i-a_i ge 0) 的情况下才是有救的

    对询问离线,考虑将所有元素从右向左一个个加入的过程,用一个 BIT 维护每个元素是否能被删除,这样待会询问的时候左端点时隐含的,我们在树状数组上查询右端点左边的部分的和就是可以删除的次数

    现在我们要动态维护这个删除过程,注意我们不会直接删除元素,只会修改它在线段树上的 (i-a_i),比如减 (1) 就代表这个元素往左移动了,设为 (infty) 就代表这个元素被删除了

    我们每次挑出最靠右的满足 (i-a_i=0) 的元素,把它在线段树上的值设为 (infty),右边的全部 (-1),然后在树状数组上修改一下

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 2e6 + 5;
    
    int tag[N], val[N];
    
    void pushup(int p)
    {
        val[p] = min(val[p * 2], val[p * 2 + 1]);
    }
    
    void put(int p, int v)
    {
        val[p] += v;
        tag[p] += v;
    }
    
    void pushdown(int p, int l = 0, int r = 0)
    {
        if (tag[p] == 0)
            return;
        put(p * 2, tag[p]);
        put(p * 2 + 1, tag[p]);
        tag[p] = 0;
    }
    
    void SegModify(int p, int l, int r, int ql, int qr, int key)
    {
        if (l > qr || r < ql)
            return;
        if (l >= ql && r <= qr)
            put(p, key);
        else
        {
            pushdown(p, l, r);
            SegModify(p * 2, l, (l + r) / 2, ql, qr, key);
            SegModify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, key);
            pushup(p);
        }
    }
    void SegModify(int p, int l, int r, int pos, int key)
    {
        if (l == r)
        {
            val[p] = key;
        }
        else
        {
            pushdown(p);
            if (pos <= (l + r) / 2)
                SegModify(p * 2, l, (l + r) / 2, pos, key);
            else
                SegModify(p * 2 + 1, (l + r) / 2 + 1, r, pos, key);
            pushup(p);
        }
    }
    int SegQuery(int p)
    {
        return val[p];
    }
    
    int SegBisect(int p, int l, int r)
    {
        if (l == r)
            return l;
        pushdown(p, l, r);
        if (val[p * 2 + 1] == 0)
            return SegBisect(p * 2 + 1, (l + r) / 2 + 1, r);
        else
            return SegBisect(p * 2, l, (l + r) / 2);
    }
    
    int arr[N];
    
    #define lowbit(x) (x & (-(x)))
    
    void BitAdd(int p)
    {
        if (p == 0)
            return;
        while (p < N)
        {
            arr[p]++;
            p += lowbit(p);
        }
    }
    
    int BitQuery(int p)
    {
        int ans = 0;
        while (p > 0)
        {
            ans += arr[p];
            p -= lowbit(p);
        }
        return ans;
    }
    
    int n, q;
    
    struct Query
    {
        int l, r, id;
        bool operator<(const Query &rhs) const
        {
            return l > rhs.l;
        }
    } que[N];
    
    int a[N], ans[N];
    
    signed main()
    {
        cin >> n >> q;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 1; i <= q; i++)
            cin >> que[i].l >> que[i].r, que[i].id = i;
        sort(que + 1, que + q + 1);
    
        int qid = 1;
    
        memset(val, 0x3f, sizeof val);
    
        for (int i = n; i >= 1; i--)
        {
            SegModify(1, 1, n, i, a[i] <= i ? i - a[i] : 1e9);
            while (SegQuery(1) == 0)
            {
                int pos = SegBisect(1, 1, n);
                BitAdd(pos);
                SegModify(1, 1, n, pos, 1e9);
                SegModify(1, 1, n, pos + 1, n, -1);
            }
            while (qid <= q && que[qid].l == i - 1)
            {
                // cout << "...";
                ans[que[qid].id] = BitQuery(n - que[qid].r);
                ++qid;
            }
        }
    
        for (int i = 1; i <= q; i++)
            cout << ans[i] << endl;
    }
    
  • 相关阅读:
    【操作系统】用Oracle VM VirtualBox 虚拟机安装XP系统时老是蓝屏
    c#操作Xml(六)
    c#操作Xml(五)
    c#操作Xml(三)
    c#操作Xml(四)
    新年快乐
    c#操作Xml(八)
    从IDataReader中读取数据实体
    c#操作Xml(七)
    c#操作Xml(二)
  • 原文地址:https://www.cnblogs.com/mollnn/p/14658965.html
Copyright © 2011-2022 走看看