2020牛客寒假算法基础集训营3 - G. 牛牛的Link Power II(线段树)

题目链接:牛牛的Link Power II

题意:给你一个只含$0$和$1$的串,定义串的$Link$值为串中两个的$1$之间的距离的和,$(u,v)$和$(v,u)$被看认为是同一对,有$m$次操作,每次操作可以把串中某个$1$变为$0$,或者把某个$0$变为$1$,求一开始和每次操作后串的$Link$值。

思路:线段树,维护区间内$1$的数量$cnt、$区间的$Link$值$w、$区间内所有的$1$到区间左边界的距离之和$dl、$区间内所有的$1$到区间右边界的距离之和$dr$,查询时只要输出$tree[1].w$即可,修改时只用改变区间内$1$的$cnt$,然后进行区间合并,区间合并的公式画个图推导一下即可。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

typedef long long ll;

const int N = 100010;
const ll mod = 1000000007;

struct node {
    int l, r;
    ll dl, dr, w, cnt;
};

node tree[4 * N];
char s[N];
int n, q;

void update(int k)
{
    tree[k].cnt = tree[2 * k].cnt + tree[2 * k + 1].cnt;
    ll t = tree[2 * k].cnt * tree[2 * k + 1].dl + tree[2 * k + 1].cnt * tree[2 * k].dr;
    tree[k].w = tree[2 * k].w + tree[2 * k + 1].w + t + tree[2 * k].cnt * tree[2 * k + 1].cnt;
    tree[k].dl = tree[2 * k].dl + tree[2 * k + 1].dl + tree[2 * k + 1].cnt * (tree[2 * k].r - tree[2 * k].l + 1);
    tree[k].dr = tree[2 * k].dr + tree[2 * k + 1].dr + tree[2 * k].cnt * (tree[2 * k + 1].r - tree[2 * k + 1].l + 1);
}

void build(int k, int lef, int rig)
{
    tree[k].l = lef, tree[k].r = rig;
    if (tree[k].l == tree[k].r) {
        tree[k].w = tree[k].dl = tree[k].dr = 0;
        if ('1' == s[tree[k].l]) tree[k].cnt = 1;
        else tree[k].cnt = 0;
        return;
    }
    int mid = (lef + rig) / 2;
    build(k * 2, lef, mid);
    build(k * 2 + 1, mid + 1, rig);
    update(k);
}

void change_point(int k, int x, int y)
{
    if (tree[k].l == tree[k].r) {
        tree[k].cnt = y;
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) change_point(2 * k, x, y);
    else change_point(2 * k + 1, x, y);
    update(k);
}

int main()
{
    scanf("%d%s", &n, s + 1);
    build(1, 1, n);
    printf("%lld\n", tree[1].w % mod);
    scanf("%d", &q);
    while (q--) {
        int kd, pos;
        scanf("%d%d", &kd, &pos);
        change_point(1, pos, 1 == kd ? 1 : 0);
        printf("%lld\n", tree[1].w % mod);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zzzzzzy/p/12286554.html