HDU

题意:

  长度为N的序列,初始时间戳为0,有M次操作。

  C l r d:代表区间[l, r]的数加d,当前时间戳加1.

  Q l r:代表输出当前时间戳内[l, r]的区间和.

  H l r t:代表输出时间戳为t时[l, r]的区间和.

  B t:代表把时间戳置为t.

题解:

  先初始化一棵带lazy线段树,之后就是主席树的做法,查询就是线段树区间求和操作。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
int n, m;
int w[maxn];
int tot, tim;
int root[maxn];
int l, r, t;
char s[5];
struct node {
    int l, r, lazy;
    ll sum;
}tre[maxn*40];
void build(int l, int r, int &x) {
    x = ++tot;
    tre[x].lazy = 0;
    if(l==r) {
        scanf("%lld", &tre[x].sum);
        return ;
    }
    int mid = l+r>>1;
    build(l, mid, tre[x].l);
    build(mid+1, r, tre[x].r);
    tre[x].sum = tre[tre[x].l].sum+tre[tre[x].r].sum;
    return ;
}
void update(int l, int r, int &x, int y, int ql, int qr, int val) {
    tre[++tot] = tre[y];
    tre[tot].sum += 1ll*(qr-ql+1)*val;
    x = tot;
    if(l==ql&&qr==r) {
        tre[x].lazy += val;
        return ;
    }
    int mid = l+r>>1;
    if(qr<=mid) update(l, mid, tre[x].l, tre[y].l, ql, qr, val);
    else if(ql>mid) update(mid+1, r, tre[x].r, tre[y].r, ql, qr, val);
    else {
        update(l, mid, tre[x].l, tre[y].l, ql, mid, val);
        update(mid+1, r, tre[x].r, tre[y].r, mid+1, qr, val);
    }
}
ll query(int l, int r, int x, int ql, int qr) {
    if(ql==l&&qr==r) return tre[x].sum;
    int mid = l+r>>1;
    ll res = 1ll*(qr-ql+1)*tre[x].lazy;
    if(qr<=mid) res += query(l, mid, tre[x].l, ql, qr);
    else if(ql>mid) res += query(mid+1, r, tre[x].r, ql, qr);
    else res += query(l, mid, tre[x].l, ql, mid)+query(mid+1, r, tre[x].r, mid+1, qr);
    return res;
}
int main() {
    int f = 0;
    while(~scanf("%d%d", &n, &m)) {
        if(f) puts("");
        f++;
        tim = tot = 0;
        build(1, n, root[0]);
        for(int i = 1; i <= m; i++) {
            scanf("%s", s);
            if(s[0]=='C') scanf("%d%d%d", &l, &r, &t), update(1, n, root[++tim], root[tim-1], l, r, t);
            if(s[0]=='Q') scanf("%d%d", &l, &r), printf("%lld
", query(1, n, root[tim], l, r));
            if(s[0]=='H') scanf("%d%d%d", &l, &r, &t), printf("%lld
", query(1, n, root[t], l, r));
            if(s[0]=='B') scanf("%d", &tim);
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/Pneuis/p/8993014.html