Clearance

Atcoder Beginner Contest 426 F

Problem Statement

AtCoder Inc.’s online shop currently handles $N$ products, and the stock of product $i$ is $A_i$ units remaining.

Process the following $Q$ orders in order. The $i$-th order is as follows:

  • Buy $k_i$ units each of products $l_i,l_i+1,\dots,r_i$. For products with fewer than $k_i$ units, buy all available units. Report the total number of products bought in this order.

Note that for $i<Q$, the stock of products bought in the $i$-th order is reduced before proceeding to the $(i+1)$-th order.

Constraints

  • All input values are integers.
  • $1 \le N \le 3 \times 10^5$
  • $1 \le A_i \le 10^{15}$
  • $1 \le Q \le 3 \times 10^5$
  • $1 \le l_i \le r_i \le N$
  • $1 \le k_i \le 10^9$

Solving

记录每个线段中,非零数值的个数,每次操作对于存在 <= k数值的区间进行暴力递归获取答案,对于区间数值均>k的区间,维护一个区间加懒标记,区间减k即可,对于判断是否存在数值,同时维护一个区间最小值即可。

由于一个数最多递归logN次,且当数值变为0时,后续操作不再参与,故时间复杂度为 O((n + q)logn)可以通过

  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
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)
struct SegTree
{
    struct Node
    {
        int l,r;
        int lo; // 当前区间最小值
        int add; // 懒加标记
        int non; // 区间非零个数
        Node() : add(0) {}
        inline int len() { return r - l + 1; }
    };

    vector<Node> tree;
    vector<int> arr;

    SegTree(const vector<int>& _arr) : arr(_arr) 
    {
        tree.resize((_arr.size() + 5) << 2,Node());
        build(1,1,_arr.size()-1);   
    }

    void push_up(int p)
    {
        tree[p].lo = min(tree[ls(p)].lo,tree[rs(p)].lo);
        tree[p].non = tree[ls(p)].non + tree[rs(p)].non;
    }

    void apply_add(int p,int val)
    {
        tree[p].lo += val;
        tree[p].add += val;
    }

    void push_down(int p)
    {
        if(tree[p].add != 0)
        {
            apply_add(ls(p),tree[p].add);
            apply_add(rs(p),tree[p].add);
            tree[p].add = 0;
        }
    }

    void build(int p,int l,int r)
    {
        tree[p].l = l;
        tree[p].r = r;
        if(l == r)
        {
            tree[p].lo = arr[l];
            tree[p].non = 1; // 初始值>0
            return;
        }
        int mid = (l + r) >> 1;
        build(ls(p),l,mid);
        build(rs(p),mid+1,r);
        push_up(p);
    }

    void updateadd(int p,int ul,int ur,int val)
    {
        if(tree[p].l >= ul and tree[p].r <= ur)
        {
            apply_add(p,val);
            return;
        }   
        push_down(p);
        int mid = (tree[p].l + tree[p].r) >> 1;
        if(ul <= mid) updateadd(ls(p),ul,ur,val);
        if(ur > mid) updateadd(rs(p),ul,ur,val);
        push_up(p);
    }
    int query(int p,int ql,int qr,int k)
    {   
        // 如果都是0,一个也选不了
        if(tree[p].non == 0) return 0;
        if(ql <= tree[p].l and tree[p].r <= qr)  
        {
            // 全部大于K,区间减K即可
            if(tree[p].lo > k) 
            {
                updateadd(p,tree[p].l,tree[p].r,-k);
                return tree[p].non * k;
            } 
            else 
            {
                // 否则暴力递归到叶子节点,暴力拾取
                if(tree[p].l == tree[p].r) 
                {
                    int temp = tree[p].lo;
                    tree[p].lo = INF;
                    tree[p].non = 0;
                    tree[p].add = 0;
                    return temp;
                }
                push_down(p);
                int res = 0;
                int mid = (tree[p].l + tree[p].r) >> 1;
                if(mid >= ql) res += query(ls(p),ql,qr,k);
                if(mid < qr) res += query(rs(p),ql,qr,k); 
                push_up(p);
                return res;
            }
        }
        else
        {
            push_down(p);
            int res = 0;
            int mid = (tree[p].l + tree[p].r) >> 1;
            if(mid >= ql) res += query(ls(p),ql,qr,k);
            if(mid < qr) res += query(rs(p),ql,qr,k);
            push_up(p);
            return res;
        }
    }   
};
void solve()
{   
    int n;
    cin >> n;
    vector<int> arr(n+1);
    for(int i=1;i<=n;i++) cin >> arr[i];
    SegTree st(arr);
    int q;
    cin >> q;
    while(q--)
    {
        int l,r,k;
        cin >> l >> r >> k;
        cout << st.query(1,l,r,k) << endl;
    }
}
Licensed under CC BY-NC-SA 4.0
Member of the Qilu University Of Technology ACM-ICPC Association
Built with Hugo
Theme Stack designed by Jimmy