• Codeforces Round #546 (Div. 2) E


    这题是一个贼搞人的线段树

    线段树维护的是 区间和a[i - j]
    首先对于update的位置可以二分查找
    其次update时候的lazy比较技巧
    比如更新的是 l-r段,增加的是c
    那么这段的值为:
    a[l] + c, a[l + 1] + k[l] + c, .... a[r] + k[l] + .. + k[r-1] + c
    lazy 记录的是 a[l] + c - (k[1] + ... + k[l - 1])
    每次pushdown的时候
    a[i]_new = lazy + k_prefix_sum[i-1]
    为了方便,我们把所有的k标号都+1

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <bitset>
    #include <algorithm>
    #include <iomanip>
    #include <cmath>
    #include <ctime>
    #include <functional>
    #include <unordered_set>
    #include <unordered_map>
    #include <string>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <complex>
    #include <cassert>
    #include <random>
    #include <cstring>
    #include <numeric>
    #define ll long long
    #define ld long double
    #define null NULL
    #define all(a) a.begin(), a.end()
    #define forn(i, n) for (int i = 0; i < n; ++i)
    #define sz(a) (int)a.size()
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
    template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
    using namespace std;
    
    const int N = 1e5 + 5;
    const ll lazyDefault = -1e18;
    
    ll a[N];
    ll k[N];
    ll kSum[N];
    ll tree[N << 2];
    ll lazy[N << 2];
    
    void pushUp(int rt) {
        tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
    }
    
    void pushDown(int rt, int l, int r) {
        if(lazy[rt] != lazyDefault) {
            int m = (l + r) >> 1;
            int lpart = (r - l + 2) / 2;
            int rpart = (r - l + 1) / 2;
    
            tree[rt << 1] = lpart * lazy[rt] + (kSum[m] - kSum[l - 1]);
            tree[rt << 1 | 1] = rpart * lazy[rt] + (kSum[r] - kSum[m]);
            
            lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
            lazy[rt] = lazyDefault;
        }
    }
    
    void build(int l, int r, int rt) {
        lazy[rt] = lazyDefault;
        if(l == r) {
            tree[rt] = a[l];
            return;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    
    ll query(int L, int R, int l, int r, int rt) {
        if(L <= l && r <= R) {
            return tree[rt];
        } 
        pushDown(rt, l, r);
        ll sum = 0;
        int m = (l + r) >> 1;
        if(L <= m) sum += query(L, R, lson);
        if(R > m) sum += query(L, R, rson);
        return sum;
    }
    
    void update(int L, int R, ll c, int l, int r, int rt) {
        if(L <= l && r <= R) {
            tree[rt] = (r - l + 1) * c + kSum[r] - kSum[l - 1];
            lazy[rt] = c;
            return;
        }
        pushDown(rt, l, r);
        int m = (l + r) >> 1;
        if(L <= m) update(L, R, c, lson);
        if(R > m) update(L, R, c, rson);
        pushUp(rt);
    }
    
    void debug(int l, int r, int rt) {
        printf("%d %d %lld
    ", l, r, tree[rt]);
        if(l == r) return;
        pushDown(rt, l, r);
        int m = (l + r) >> 1;
        debug(lson);
        debug(rson);
    }
    
    int main() {
        int n;
        while(~scanf("%d", &n)) {
            for(int i = 1; i <= n; ++i) {
                scanf("%lld", &a[i]);
            }
    
            for(int i = 2; i <= n; ++i) {
                scanf("%lld", &k[i]);
                k[i] += k[i-1];
            }
            for(int i = 2; i <= n; ++i) {
                kSum[i] += kSum[i-1] + k[i];
            }
    
            build(1,n,1);
            
            int q;
            scanf("%d", &q);
            while(q -- ) {
                char s[10]; int x, y;
                scanf("%s %d %d", s, &x, &y);
                if(s[0] == '+') {
                    int l = x; int r = n;
                    ll tmp = query(x, x, 1, n, 1);
                    while(l <= r) {
                        int m = (l + r) >> 1;
                        ll tmp2 = query(m, m, 1, n, 1);
                        if(tmp2 - tmp - y > k[m] - k[x]) r = m - 1;
                        else l = m + 1;
                    }
                    // printf("choose: %d
    ", r);
                    update(x, r, tmp + y - k[x], 1, n, 1);               
                } else {
                    printf("%lld
    ", query(x, y, 1, n, 1));
                }
                // debug(1, n, 1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    从无到有实现登录功能以及thinkphp怎么配置数据库信息
    Navicat软件中mysql中int、bigint、smallint和tinyint的区别、布尔类型存储以及乱码问题的解决
    ThinkPHP实现对数据库的增删改查
    ListView实现点击事件以及总结
    仿迅雷播放器教程 -- 提取exe资源(12)
    仿迅雷播放器教程 -- C++ windows界面库对比(11)
    仿迅雷播放器教程 -- C++ 100款开源界面库 (10)
    仿迅雷播放器教程 -- C++界面制作方法的对比 (9)
    仿迅雷播放器教程 -- 权威界面库对比 (8)
    仿迅雷播放器教程 -- 十年经验大牛对MFC的认识 (7)
  • 原文地址:https://www.cnblogs.com/Basasuya/p/10686523.html
Copyright © 2020-2023  润新知