牛客-牛牛的Link Power II

题目传送门

sol:可以用线段树来维护,线段树的节点除了标配的$l$和$r$同时记录该区间$link$的个数记为$cnt$,该区间$link$点的和记为$sum$,该区间题目中所谓的能量记为$dis$。然后$cnt$和$sum$就直接两个儿子相加就好,$dis$还要另外加上$segTree[rs].sum * segTree[ls].cnt - segTree[ls].sum * segTree[rs].cnt$这部分。

  • 线段树
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = 1e5 + 10;
    const int MOD = 1e9 + 7;
    struct Node {
        int l, r;
        int cnt;
        int sum, dis;
    } segTree[4 * MAXN];
    void push_up(int i) {
        int ls = i << 1, rs = i << 1 | 1;
        segTree[i].cnt = segTree[ls].cnt + segTree[rs].cnt;
        segTree[i].sum = (segTree[ls].sum + segTree[rs].sum) % MOD;
        segTree[i].dis = (1LL * segTree[rs].sum * segTree[ls].cnt - 1LL * segTree[ls].sum * segTree[rs].cnt) % MOD;
        segTree[i].dis = (1LL * MOD + segTree[i].dis + segTree[ls].dis + segTree[rs].dis) % MOD;
    }
    void build(int i, int l, int r) {
        segTree[i].l = l;
        segTree[i].r = r;
        if (l == r) {
            int k = getchar() ^ '0';
            segTree[i].cnt = k;
            segTree[i].sum = k * l;
            return;
        }
        int mid = l + r >> 1;
        build(i << 1, l, mid);
        build(i << 1 | 1, mid + 1, r);
        push_up(i);
    }
    void update(int i, int k, int data) {
        if (segTree[i].l == segTree[i].r) {
            segTree[i].cnt = data;
            segTree[i].sum = data * segTree[i].l;
            return;
        }
        int mid = segTree[i].l + segTree[i].r >> 1;
        if (k <= mid) update(i << 1, k, data);
        else update(i << 1 | 1, k, data);
        push_up(i);
    }
    int main() {
        int n; scanf("%d%*c", &n);
        build(1, 1, n);
        printf("%d\n", segTree[1].dis);
        int q; scanf("%d", &q);
        while (q--) {
            int op, k;
            scanf("%d%d", &op, &k);
            if (op == 1) update(1, k, 1);
            else update(1, k, 0);
            printf("%d\n", segTree[1].dis);
        }
        return 0;
    }

    这个线段树如果要查询某个区间的dis其实不大好写,但是题目中所有的查询都是针对整棵树,也就是segTree[1]。所以省掉了询问函数。

posted @ 2020-02-09 20:55  Angel_Demon  阅读(...)  评论(...编辑  收藏