zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营3

    题目链接:牛牛的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
    ", 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
    ", tree[1].w % mod);
        }
        return 0;
    }
  • 相关阅读:
    Cassandra开发入门文档第三部分(非规范化关系结构、批处理)
    Cassandra开发入门文档第二部分(timeuuid类型、复合主键、静态字段详解)
    Cassandra开发入门文档第一部分
    Flume的Source、Sink总结,及常用使用场景
    Libgdx学习笔记:分享自己写的异步加载
    jquery easyui toolbar 分割线问题
    easyui datagrid设置fit: true后,页面显示不全的情况
    CentOS下安装JDK1.7
    CentOS 7搭建SVN服务器
    SWT中ole/activex实践--操作word的一个例子
  • 原文地址:https://www.cnblogs.com/zzzzzzy/p/12286554.html
Copyright © 2011-2022 走看看