2020ICPC小米網路賽 C.Data Structure Problem

qq_45323960發表於2020-12-31

題目連結
題目描述
Bobo has two sequences a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an and b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn. He would like to perform the following operations:

  • 1  x   y \text{1 }x\ y x y, change the value of a x a_x ax to y y y.
  • 2  x   y \text{2 }x\ y x y, change the value of b x b_x bx to y y y.
  • 3  x \text{3 }x x, find the value of c x c_x cx, where c 0 = 0 c_0=0 c0=0, c i = max ⁡ ( c i − 1 + b i , a i )  for  1 ≤ i ≤ x c_i=\max(c_{i-1}+b_i,a_i) \text{ for } 1 \le i \le x ci=max(ci1+bi,ai) for 1ix.

輸入描述:
The input consists of several test cases terminated by end-of-file. For each test case:

The first line contains two integers n n n and m m m , which are the length of the two sequences and the number of operations. The second line contains n n n integers a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an. The third line contains n n n integers b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn. Each of the last m lines contains a query.

  • 1 ≤ n , m ≤ 2 × 1 0 5 1 \leq n, m \leq 2 \times 10^5 1n,m2×105

  • − 1 0 9 ≤ a i , b i , y ≤ 1 0 9 -10^9 \leq a_i, b_i, y \leq 10^9 109ai,bi,y109

  • 1 ≤ x ≤ n 1 \leq x \leq n 1xn

  • The sum of n n n and the sum of m m m do not exceed 2 × 1 0 6 2 \times 10^6 2×106.

輸出描述:
For each query of 3  x \text{3 }x x, output an integer denoting the value of c x c_x cx.
示例1
輸入

4 9
1 2 3 3
-1 2 3 3
3 1
3 2
3 3
3 4
2 2 -4
3 1
3 2
3 3
3 4

輸出

1
3
6
9
1
2
5
8

定義 a n s ( l , r ) = c r ans(l,r)=c_r ans(l,r)=cr c l − 1 = 0 c_{l-1}=0 cl1=0 c i = max ⁡ ( c i − 1 + b i , a i )  for  l ≤ i ≤ r c_i=\max(c_{i-1}+b_i,a_i) \text{ for } l \le i \le r ci=max(ci1+bi,ai) for lir s u m ( l , r ) = ∑ i = l r b i sum(l,r)=\sum\limits_{i=l}^rb_i sum(l,r)=i=lrbi
則對於兩個區間 [ l , x ] [l,x] [l,x] [ x + 1 , r ] [x+1,r] [x+1,r] ,滿足 a n s ( l , r ) = max ⁡ ( a n s ( l , x ) + s u m ( x + 1 , r ) , a n s ( x + 1 , r ) ) ans(l,r)=\max(ans(l,x)+sum(x+1,r),ans(x+1,r)) ans(l,r)=max(ans(l,x)+sum(x+1,r),ans(x+1,r))
用反證法很好證明。用線段樹維護即可。

#include<bits/stdc++.h>

#define ll long long
#define fi first
#define se second
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e5 + 10;
const ll INF = 4e18;

struct Seg_Tree {
    struct {
        int l, r;
        ll sum, ans;
    } t[N * 4];

#define update(x) {                                                          \
        t[x].sum = t[x << 1].sum + t[x << 1 | 1].sum;                        \
        t[x].ans = max(t[x << 1].ans + t[x << 1 | 1].sum, t[x << 1 | 1].ans);\
    }                                                                        \


    void build(int p, int l, int r, const int *a, const int *b) {
        t[p].l = l, t[p].r = r;
        if (l == r) {
            t[p].ans = a[l];
            t[p].sum = b[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(p << 1, l, mid, a, b);
        build(p << 1 | 1, mid + 1, r, a, b);
        update(p)
    }

    void changea(int p, int x, int v) {
        if (t[p].l == t[p].r) {
            t[p].ans = v;
            return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid)changea(p << 1, x, v);
        else changea(p << 1 | 1, x, v);
        update(p)
    }

    void changeb(int p, int x, int v) {
        if (t[p].l == t[p].r) {
            t[p].sum = v;
            return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid)changeb(p << 1, x, v);
        else changeb(p << 1 | 1, x, v);
        update(p)
    }

    pair<ll, ll> ask(int p, int x) {
        if (t[p].l > x)return {0, -INF};
        if (t[p].r <= x)return {t[p].sum, t[p].ans};
        pair<ll, ll> val = ask(p << 1, x);
        pair<ll, ll> res = ask(p << 1 | 1, x);
        val.fi += res.fi, val.se = max(val.se + res.fi, res.se);
        return val;
    }
} S;

int a[N], b[N], n, m;

int main() {
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 2; i <= n + 1; ++i)a[i] = qr();
        for (int i = 2; i <= n + 1; ++i)b[i] = qr();
        S.build(1, 1, n + 1, a, b);
        for (int i = 1; i <= m; ++i)
            switch (qr()) {
                case 1: {
                    int x = qr(), y = qr();
                    S.changea(1, x + 1, y);
                    break;
                }
                case 2: {
                    int x = qr(), y = qr();
                    S.changeb(1, x + 1, y);
                    break;
                }
                default:
                    printf("%lld\n", S.ask(1, qr() + 1).se);
            }
    }
    return 0;
}

相關文章