zoukankan      html  css  js  c++  java
  • 数据结构

    序列操作

    单点加,前缀和查询:

    树状数组直接维护即可。

    区间加,单点查询:

    设原数组为 $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]$ 即可。

  • 相关阅读:
    jsp简单自定义标签demo展示《二》
    jsp自定义标签介绍《一》
    登陆filter
    中文乱码原因以及解决方案
    C++ 中注意,零扩展和符号位扩展
    linux下的a.out文件
    今天谈谈流,什么是IO流?
    windows下的c语言和linux 下的c语言以及C标准库和系统API
    一维数组的数组指针
    结构体指针传参与返回值
  • 原文地址:https://www.cnblogs.com/qqq1112/p/14083134.html
Copyright © 2011-2022 走看看