线段树

区间修改

#define int long long

const int maxn = 3e5 + 7;
int a[maxn];
struct node {
    int l, r, sum, lz;
} tr[maxn << 4];

void push_up(int p) {
    tr[p].sum = tr[p << 1].sum + tr[p << 1 | 1].sum;
}

void push_down(int p) {
    if (tr[p].lz != 0) {
        tr[p << 1].sum += (tr[p << 1].r - tr[p << 1].l + 1) * tr[p].lz;
        tr[p << 1 | 1].sum += (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1) * tr[p].lz;
        tr[p << 1].lz += tr[p].lz;
        tr[p << 1 | 1].lz += tr[p].lz;
        tr[p].lz = 0;
    }
}

void build(int p, int l, int r) {
    tr[p].l = l, tr[p].r = r;
    tr[p].lz = 0;
	if (l == r) {
        tr[p].sum = a[l];
        return;
    }
    int mi = (l + r) >> 1;
    build(p << 1, l, mi);
    build(p << 1 | 1, mi + 1, r);
    push_up(p);
}

void update(int p, int l, int r, int val) {
    if (l <= tr[p].l && tr[p].r <= r) {
        tr[p].lz += val;
        tr[p].sum += (tr[p].r - tr[p].l + 1) * val;
        return;
    }
    push_down(p);
    int mi = (tr[p].l + tr[p].r) >> 1;
    if (l <= mi) update(p << 1, l, r, val);
    if (r > mi) update(p << 1 | 1, l, r, val);
    push_up(p);
}

int res;

void query(int p, int l, int r) {
    if (l <= tr[p].l && tr[p].r <= r) {
        res += tr[p].sum;
        return;
    }
    push_down(p);
    int mi = (tr[p].l + tr[p].r) >> 1;
    if (l <= mi) query(p << 1, l, r);
    if (r > mi) query(p << 1 | 1, l, r);
    push_up(p);
}

int n, t, m;

void solve() {
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    build(1, 1, n);
    for (int i = 1; i <= m; i++) {
        char op;
        int l, r, val;
        scanf(" %c", &op);
        if (op == 'Q') {
            scanf("%lld%lld", &l, &r);
            res = 0;
            query(1, l, r);
            printf("%lld", res);
            if (i != m) puts("");
        } else {
            scanf("%lld%lld%lld", &l, &r, &val);
            update(1, l, r, val);
        }
    }
}

add,mul,chg - 多lz标签维护


const int maxn = 1e5 + 7;
const int mod = 10007;

struct node {
    int l, r, sum[3], add, mul, chg;
} tr[maxn << 2];

void push_up(int p) {
    for (int i = 0; i <= 2; i++)
        tr[p].sum[i] = (tr[p << 1].sum[i] + tr[p << 1 | 1].sum[i]) % mod;
}

void build(int p, int l, int r) {
    tr[p] = {l, r, 0, 0, 0, 0, 1, -1};
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
}

void chg(int p, int x) {
    tr[p].chg = x;
    tr[p].sum[2] = x * x % mod * x % mod * (tr[p].r - tr[p].l + 1) % mod;
    tr[p].sum[1] = x * x % mod * (tr[p].r - tr[p].l + 1) % mod;
    tr[p].sum[0] = x * (tr[p].r - tr[p].l + 1) % mod;
    tr[p].add = 0, tr[p].mul = 1;
}

void mul(int p, int x) {
    tr[p].mul = tr[p].mul * x % mod;
    tr[p].add = tr[p].add * x % mod;
    tr[p].sum[2] = tr[p].sum[2] * x % mod * x % mod * x % mod;
    tr[p].sum[1] = tr[p].sum[1] * x % mod * x % mod;
    tr[p].sum[0] = tr[p].sum[0] * x % mod;
}

void add(int p, int x) {
    tr[p].add = (tr[p].add + x) % mod;
    tr[p].sum[2] = (tr[p].sum[2]
                    + 3 * tr[p].sum[1] % mod * x % mod
                    + 3 * tr[p].sum[0] % mod * x % mod * x % mod
                    + x * x % mod * x % mod * (tr[p].r - tr[p].l + 1)) % mod;

    tr[p].sum[1] = (tr[p].sum[1]
                    + 2 * tr[p].sum[0] % mod * x
                    + (tr[p].r - tr[p].l + 1) * x % mod * x % mod) % mod;

    tr[p].sum[0] = (tr[p].sum[0]
                    + (tr[p].r - tr[p].l + 1) * x % mod) % mod;
}

void push_down(int p) {
    if (tr[p].chg != -1) {
        chg(p << 1, tr[p].chg), chg(p << 1 | 1, tr[p].chg);
        tr[p].chg = -1;
    }
    if (tr[p].mul != 1) {
        mul(p << 1, tr[p].mul), mul(p << 1 | 1, tr[p].mul);
        tr[p].mul = 1;
    }
    if (tr[p].add) {
        add(p << 1, tr[p].add), add(p << 1 | 1, tr[p].add);
        tr[p].add = 0;
    }
}

void update(int p, int l, int r, int x, int opt) {
    if (l <= tr[p].l && tr[p].r <= r) {
        if (opt == 3) {
            chg(p, x);
        } else if (opt == 2) {
            mul(p, x);
        } else add(p, x);
        return;
    }
    push_down(p);
    int mid = (tr[p].l + tr[p].r) >> 1;
    if (l <= mid) update(p << 1, l, r, x, opt);
    if (r > mid) update(p << 1 | 1, l, r, x, opt);
    push_up(p);
}

int res = 0;

void query_sum(int p, int l, int r, int id) {
    if (l <= tr[p].l && tr[p].r <= r) {
        res += tr[p].sum[id];
        res %= mod;
        return;
    }
    push_down(p);
    int mid = (tr[p].l + tr[p].r) >> 1;
    if (l <= mid) query_sum(p << 1, l, r, id);
    if (r > mid) query_sum(p << 1 | 1, l, r, id);
    push_up(p);
}

int n, t, m;

void solve() {
    while (cin >> n >> m && n) {
        build(1, 1, n);
        for (int i = 1, opt, l, r, k; i <= m; i++) {
            cin >> opt >> l >> r >> k;
            if (opt == 4) {
                res = 0, query_sum(1, l, r, k - 1);
                cout << res << endl;
            } else {
                update(1, l, r, k, opt);
            }
        }
    }
}

区间合并

每个节点维护三个值:lmx,rmx,mx
lmx固定左端点开始的最大长度
mx为区间最大长度
区间合并时,用左儿子lmx更新lmx,右儿子rmx更新rmx,判断能不能跨过mid
mx取左右儿子的mx和左儿子rmx+右儿子lmx的 max

主要就是push_up需要注意

void push_up(int id, int p) {
    node &lson = tr[id][p << 1], &rson = tr[id][p << 1 | 1], &rt = tr[id][p];
    rt.lmx = lson.lmx;
    rt.rmx = rson.rmx;
    int mid = (rt.l + rt.r) >> 1;
    if (rt.lmx == mid - rt.l + 1) rt.lmx += rson.lmx;
    if (rt.rmx == rt.r - mid) rt.rmx += lson.rmx;
    rt.mx = max(max(lson.mx, rson.mx), lson.rmx + rson.lmx);
}
const int maxn = 2e5 + 7;

int n, t, m, ti;

struct node {
    int l, r, lmx, rmx, mx, lz;
} tr[2][maxn << 2];

void push_up(int id, int p) {
    node &lson = tr[id][p << 1], &rson = tr[id][p << 1 | 1], &rt = tr[id][p];
    rt.lmx = lson.lmx;
    rt.rmx = rson.rmx;
    int mid = (rt.l + rt.r) >> 1;
    if (rt.lmx == mid - rt.l + 1) rt.lmx += rson.lmx;
    if (rt.rmx == rt.r - mid) rt.rmx += lson.rmx;
    rt.mx = max(max(lson.mx, rson.mx), lson.rmx + rson.lmx);
}

void push_down(int id, int p) {
    node &lson = tr[id][p << 1], &rson = tr[id][p << 1 | 1], &rt = tr[id][p];
    if (rt.lz != -1) {
        int lz = rt.lz, mid = (rt.l + rt.r) >> 1, l = rt.l, r = rt.r, le = mid - l + 1, re = r - mid;
        lson = {l, mid, le * lz, le * lz, le * lz, lz};
        rson = {mid + 1, r, re * lz, re * lz, re * lz, lz};
        rt.lz = -1;
    }
}

void build(int id, int p, int l, int r) {
    tr[id][p] = {l, r, r - l + 1, r - l + 1, r - l + 1, -1};
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(id, p << 1, l, mid);
    build(id, p << 1 | 1, mid + 1, r);
    push_up(id, p);
}

void update(int id, int p, int l, int r, int x) {
    node &rt = tr[id][p];
    if (l <= rt.l && rt.r <= r) {
        int lr = rt.r - rt.l + 1;
        rt = {rt.l, rt.r, lr * x, lr * x, lr * x, x};
        return;
    }
    push_down(id, p);
    int mid = (rt.l + rt.r) >> 1;
    if (l <= mid) update(id, p << 1, l, r, x);
    if (r > mid) update(id, p << 1 | 1, l, r, x);
    push_up(id, p);
}

int query(int id, int p, int x) {
    node &lson = tr[id][p << 1], &rson = tr[id][p << 1 | 1], &rt = tr[id][p];
    if (rt.l == rt.r) return rt.l;
    push_down(id, p);
    int mid = (rt.l + rt.r) >> 1;
    if (lson.mx >= x) return query(id, p << 1, x);
    if (lson.rmx + rson.lmx >= x) return mid - lson.rmx + 1;
    return query(id, p << 1 | 1, x);
}

char op[20];

void solve() {
    cin >> t;
    while (t--) {
        scanf("%d%d", &n, &m);
        build(0, 1, 1, n);
        build(1, 1, 1, n);
        printf("Case %d:\n", ++ti);
        for (int i = 1, x, y, l, r; i <= m; i++) {
            scanf("%s%d", op, &x);
            if (op[0] == 'D') {
                if (tr[0][1].mx >= x) {
                    l = query(0, 1, x);
                    printf("%d,let's fly\n", l);
                    update(0, 1, l, l + x - 1, 0);
                } else printf("fly with yourself\n");
            } else if (op[0] == 'N') {
                if (tr[0][1].mx >= x) {
                    l = query(0, 1, x);
                    printf("%d,don't put my gezi\n", l);
                    update(0, 1, l, l + x - 1, 0);
                    update(1, 1, l, l + x - 1, 0);
                } else if (tr[1][1].mx >= x) {
                    l = query(1, 1, x);
                    printf("%d,don't put my gezi\n", l);
                    update(0, 1, l, l + x - 1, 0);
                    update(1, 1, l, l + x - 1, 0);
                } else printf("wait for me\n");
            } else {
                scanf("%d", &y);
                printf("I am the hope of chinese chengxuyuan!!\n");
                update(0, 1, x, y, 1);
                update(1, 1, x, y, 1);
            }
        }
    }
}

动态开点


const int maxn = 2.7e5 + 7;
const int all = 1e9 + 7;
int n, t, m, tot, q, rt = 0, l, r, k;
struct node {
    int sum, lz, ls, rs, l, r;
} tr[maxn * 40];

void push_down(int p) {
    if (tr[p].lz == -1) return;
    node &rt = tr[p];
    if (!rt.ls) rt.ls = ++tot;
    if (!rt.rs) rt.rs = ++tot;
    int mid = (rt.l + rt.r) / 2;
    tr[rt.ls].sum = (mid - rt.l + 1) * rt.lz;
    tr[rt.rs].sum = (rt.r - mid) * rt.lz;
    tr[rt.ls].lz = tr[rt.rs].lz = rt.lz;
    rt.lz = -1;
}

void update(int &p, int trl, int trr, int l, int r, int x) {
    if (!p) p = ++tot;
    tr[p].l = trl, tr[p].r = trr;
    if (l <= tr[p].l && tr[p].r <= r) {
        tr[p].lz = x;
        tr[p].sum = (tr[p].r - tr[p].l + 1) * x;
        return;
    }
    push_down(p);
    int mid = (tr[p].l + tr[p].r) >> 1;
    if (l <= mid) update(tr[p].ls, tr[p].l, mid, l, r, x);
    if (r > mid) update(tr[p].rs, mid + 1, tr[p].r, l, r, x);
    tr[p].sum = tr[tr[p].ls].sum + tr[tr[p].rs].sum;
}

void solve() {
    scanf("%d%d", &n, &q);
    for (int i = 0; i < maxn * 40; i++) tr[i].lz = -1;
    while (q--) {
        scanf("%d%d%d", &l, &r, &k);
        k == 2 ? k = 0 : k = 1;
        update(rt, 1, all, l, r, k);
        printf("%d\n", n - tr[1].sum);
    }
}

多颗线段树+动态开点

https://codeforces.com/contest/1046/problem/A

#define int long long

const int maxn = 1e5 + 7;
const int all = 1e9 + 7;

int n, t, k, m, dfn = 21;
struct node {
    int sum, lz, ls, rs, l, r;
} tr[maxn * 40];

struct boot {
    int x, r, q;
} b[maxn];

bool cmp(boot a, boot b) {
    return a.r > b.r;
}

void update(int &p, int pl, int pr, int ps) {
    if (!p) p = ++dfn;
    tr[p].sum++, tr[p].l = pl, tr[p].r = pr;
    if (pl == pr) return;
    int mid = (pl + pr) / 2;
    if (ps <= mid) update(tr[p].ls, pl, mid, ps);
    else update(tr[p].rs, mid + 1, pr, ps);
}

int query(int p, int l, int r) {
    if (!p) return 0;
    if (l <= tr[p].l && tr[p].r <= r)
        return tr[p].sum;
    int mid = (tr[p].l + tr[p].r) >> 1, res = 0;
    if (l <= mid) res += query(tr[p].ls, l, r);
    if (r > mid) res += query(tr[p].rs, l, r);
    return res;
}

int rt[maxn];
map<int, int> mp;

void solve() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> b[i].x >> b[i].r >> b[i].q;
    }
    ll ans = 0;
    sort(b + 1, b + 1 + n, cmp);
    for (int i = 1; i <= n; i++) {
        int l = max(0ll, b[i].x - b[i].r);
        int r = min(all, b[i].x + b[i].r);
        int a = max(0ll, b[i].q - k);
        int c = min(all, b[i].q + k);
        for (int x = a; x <= c; x++) {
            if (mp.count(x) == 0) continue;
            ans += query(mp[x], l, r);
        }
        if (mp[b[i].q] == 0) mp[b[i].q] = ++dfn;
        update(mp[b[i].q], 0, all, b[i].x);
    }
    cout << ans << endl;
}

线段树合并

https://www.luogu.com.cn/problem/P3605

const int maxn = 1e5 + 7;

int n, tot = maxn - 1;

int rt[maxn], a[maxn], b[maxn], ans[maxn], dfn;
vector<int> mp[maxn];

struct node {
    int sum, l, r, ls, rs;
} tr[maxn * 40];

void push_up(int p) {
    tr[p].sum = tr[tr[p].ls].sum + tr[tr[p].rs].sum;
}

int merge(int p, int q, int l, int r) {
    if (!p || !q) return p | q;
    if (l == r) {
        tr[p].sum += tr[q].sum;
        return p;
    }
    int mid = (l + r) >> 1;
    tr[p].ls = merge(tr[p].ls, tr[q].ls, l, mid);
    tr[p].rs = merge(tr[p].rs, tr[q].rs, mid + 1, r);
    push_up(p);
    return p;
}

int query(int p, int l, int r) {
    if (!p) return 0;
    if (l <= tr[p].l && tr[p].r <= r)
        return tr[p].sum;
    int mid = (tr[p].l + tr[p].r) >> 1, res = 0;
    if (l <= mid) res += query(tr[p].ls, l, r);
    if (r > mid) res += query(tr[p].rs, l, r);
    return res;
}

void update(int &p, int pl, int pr, int ps) {
    if (!p) p = ++dfn;
    tr[p].sum++, tr[p].l = pl, tr[p].r = pr;
    if (pl == pr) return;
    int mid = (pl + pr) / 2;
    if (ps <= mid) update(tr[p].ls, pl, mid, ps);
    else update(tr[p].rs, mid + 1, pr, ps);
}

void dfs(int u) {
    for (auto v:mp[u]) {
        dfs(v);
        merge(rt[u], rt[v], 1, tot);
    }
    update(rt[u], 1, tot, a[u]);
    ans[u] = query(rt[u], a[u] + 1, tot);
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b + 1, b + 1 + n);
    for (int i = 1; i <= n; i++)
        a[i] = lower_bound(b + 1, b + 1 + n, a[i]) - b;
    for (int i = 2, f; i <= n; i++) {
        cin >> f;
        mp[f].push_back(i);
    }
    for (int i = 1; i <= n; i++)
        rt[i] = ++dfn;
    dfs(1);
    for (int i = 1; i <= n; i++)
        cout << ans[i] << "\n";
}


posted @ 2021-08-11 18:55  naymi  阅读(32)  评论(0)    收藏  举报