HDU - 4348 [To the moon] Standard Online Chairman tree

HDU - 4348 [To the moon] Standard Online Chairman tree

https://cn.vjudge.net/contest/304073#problem/G

The meaning of problems

M and n number given operations, start time is 0, the operation is divided into four categories:

  • Q xy - interrogation [x, y] of the node and the current time interval

  • C xyz - the [x, y] where the number of all sections plus z, the current time + 1 node

  • H xyz - interrogation [x, y] z in the time interval and the node

  • B x - x node becomes the current time

analysis

Few questions before they did belong to the "right value segment tree" (tree each node stored value \ (sum \) represents the number of the current number), hence the need for discrete, representing each number with a label .

The existence of this problem each node of the tree need to build value \ (sum \) is the conventional segment tree, is the true meaning of the interval and (because the topics on request and interval).

For the update interval, we can use an array lazy. From the recursion down time, we can sum this parent node, direct update. When faced with a given query interval and the interval just completely coincide, we need to update lazy. Doing so can save pushdown of complex operations.

When queried, we need to find all the intervals are lazy plus.

See specific operation code.

Code

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

const int maxn = 1e5 + 5;

int n, m, cnt;
ll a[maxn];
int root[maxn];
struct node {
    int l, r;
    ll sum, lazy;
}T[maxn*40];

void init() {
    cnt = 0;
}

void build(int l, int r, int &rt) {
    rt = ++ cnt;
    T[rt].l = l;
    T[rt].r = r;
    T[rt].sum = a[l];
    T[rt].lazy = 0;
    if(l == r) {
        return ;
    }
    int mid = (l+r) / 2;
    build(l, mid, T[rt].l);
    build(mid+1, r, T[rt].r);
    T[rt].sum = T[T[rt].l].sum + T[T[rt].r].sum;
}

void update(int L, int R, int l, int r, int &x, int y, ll c) {
    T[++cnt] = T[y];
    T[cnt].sum += c*(R-L+1);// 把每个区间的增量都算上
    x = cnt;
    if(L == l && R == r) {
        T[cnt].lazy += c; // 正好重合时更新lazy标记
        return ;
    }
    int mid = (l+r) / 2;
    // 区间更新
    if(mid >= R) {
        update(L, R, l, mid, T[x].l, T[y].l, c);
    }
    else if(mid < L) {
        update(L, R, mid+1, r, T[x].r, T[y].r, c);
    }
    else {
        update(L, mid, l, mid, T[x].l, T[y].l, c);
        update(mid+1, R, mid+1, r, T[x].r, T[y].r, c);
    }
}

ll query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
        return T[rt].sum;
    }
    ll ans = T[rt].lazy*(R-L+1);    // 每个需要找的区间都得加
    int mid = (l+r) / 2;
    if(mid >= R) {
        ans += query(L, R, l, mid, T[rt].l);
    }
    else if(mid < L) {
        ans += query(L, R, mid+1, r, T[rt].r);
    }
    else {
        ans += query(L, mid, l, mid, T[rt].l);
        ans += query(mid+1, R, mid+1, r, T[rt].r);
    }
    return ans;
}

int main() {
    while(~scanf("%d%d", &n, &m)) {
        init();
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);     // 非权值线段树,不需要离散化,存的是原数
        }
        build(1, n, root[0]);
       // cout << T[1].sum << endl;
        int now_time = 0;
        for(int i = 1; i <= m; i++) {
            char f[10];
            int x, y, t;
            ll c;
            scanf("%s", f);
            if(f[0] == 'Q') {
                scanf("%d%d", &x, &y);
                printf("%lld\n", query(x, y, 1, n, root[now_time]));
            }
            else if(f[0] == 'C') {
                scanf("%d%d%lld", &x, &y, &c);
                now_time ++;
                update(x, y, 1, n, root[now_time], root[now_time-1], c);
            }
            else if(f[0] == 'H') {
                scanf("%d%d%d", &x, &y, &t);
                printf("%lld\n", query(x, y, 1, n, root[t]));
            }
            else {
                scanf("%d", &t);
                now_time = t;
            }
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Decray/p/10930792.html