• 数据结构


    序列操作

    单点加,前缀和查询:

    树状数组直接维护即可。

    区间加,单点查询:

    设原数组为 $a[i]$ ,并更新一个数组 $c[i]$ $=$ $a[i]$ $-$ $a[i$ $-$ $1]$即为差分数组;

    每次区间 $(l,$ $r)$ $+$ $x$ 直接$c[l]$ $+$ $x$,c[r + 1] - x即可;

    最后求第i个数的答案就是 $∑$ $c[i]$。

    区间加,前缀和查询:

    设原数组为a[i],同样

    树链加,单点查询(处理节点):

    用树上差分进行解决;

    设 $d[i]$ 表示第 $i$ 个节点到根节点 $root$ 的修改量,只记录修改量,相当于树的差分数组;

    假设将 $u$ 到 $v$ 的路径上的点都加上 $a$,并且满足条件 $u$ 是 $v$ 的祖先或 $v$ 是 $u$ 的祖先,那么便可以像正常差分一样 $d[u]$ $+=$ $a$,$d[fa[v]]$ $-=$ $a$。

    对于更新一个不一定有祖先关系的树链 $(u,$ $v)$ ,即希望将 $u$ 到 $v$ 的路径上都加上 $a$ ,怎么求呢?

    如图所示,希望更改路径 $(u,$ $v)$ 上的点权,那么只需进行一下操作:

    • $d[u]$ $+=$ $a$;
    • $d[v]$ $+=$ $a$;
    • $d[lca(u,$ $v)]$ $-=$ $a$;
    • $d[fa[lca(u,$ $v)]]$ $-=$ $a$;

    证明图中可以很清晰的看出来。

    如果要查询一个点的修改量,那么很容易得出这个点的修改量就是它的子树的 $d[i]$ 之和,树状数组直接维护即可(转化成 $dfs$ 序)。

    如果要查询一个子树的修改量之和,那么就是 $∑$ $∑$ $d[j]$ (其中 $j$ 是 $i$ 的子孙, $i$ 是当前查询的子树的根 $u$ 的子孙);

    经过化简后可以得出就是 $∑$ $d[i]$ $*$ $(depth[i]$ $-$ $depth[u]$ $+$ $1)$ (其中 $i$ 是 $u$ 的子孙, $depth[i]$ 表示 $i$ 的深度);

    再进行转化后可以得出就是 $(∑$ $d[i]$ $*$ $depth[i])$ $-$ $((depth[u]$ $-$ $1)$ $*$ $(∑$ $d[i]))$;

    然后用树状数组维护 $∑$ $d[i]$ $*$ $depth[i]$ 和 $∑$ $d[i]$ 即可。

  • 相关阅读:
    音频播放器
    SQL Server找不到配置管理器怎么办
    SQL——游标循环的写法
    SQL——多条相似内容只取一条
    SQL——delete left join
    SQL——查询包含某字段的所有表
    SQL——获取数据库表结构
    SQL Server数据库改名
    SQL——left join的结果行数可能大于左表
    SQL——用临时表代替过多的变量声明赋值
  • 原文地址:https://www.cnblogs.com/qqq1112/p/14083134.html
Copyright © 2020-2023  润新知