zoukankan      html  css  js  c++  java
  • 树链剖分

    树链剖分是基于重孩子将树划分成若干条链,配上对应的数据结构(例如这里的线段树)就可以维护树中的链,甚至可以直接维护子树。

    貌似还有更高级的$ ext{LCT}$,要搭配$ ext{Splay}$。正在学习中。

    具体证明。。待更。。

    源码如下。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define re register
      6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
      7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
      8 #define For(i, a, b, s) for (re int i = a; i <= b; s)
      9 #define maxx(a, b) a = max(a, b)
     10 #define minn(a, b) a = min(a, b)
     11 #define LL long long
     12 #define INF (1 << 30)
     13 
     14 inline int read() {
     15     int w = 0, f = 1; char c = getchar();
     16     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
     17     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
     18     return w * f;
     19 }
     20 
     21 const int maxn = 1e5 + 5;
     22 
     23 int N, M, R, P;
     24 
     25 struct Edge {
     26     int u, v, pre;
     27 } e[maxn << 1];
     28 int ec, G[maxn];
     29 void init() { ec = 0; memset(G, -1, sizeof(G)); }
     30 void add(int u, int v) { e[ec++] = (Edge){u, v, G[u]}; G[u] = ec-1; }
     31 #define iter(i, u) for (register int i = G[u]; i != -1; i = e[i].pre)
     32 // 
     33 
     34 int a[maxn], val[maxn]; // a按照下文mark的顺序
     35 struct SegT {
     36 #define lson (o << 1)
     37 #define rson (o << 1 | 1)
     38     int sumv[maxn << 4], tag[maxn << 4];
     39     void pushup(int o) { sumv[o] = sumv[lson] + sumv[rson]; }
     40     void pushdown(int o, int l, int r) {
     41         if (!tag[o]) return;
     42         tag[lson] += tag[o]; tag[rson] += tag[o];
     43         int mid = (l + r) >> 1;
     44         sumv[lson] = (sumv[lson] + (LL)tag[o] * (mid - l + 1)) % P; sumv[rson] = (sumv[rson] + (LL)tag[o] * (r - mid)) % P;
     45         tag[o] = 0;
     46     }
     47     void build(int o, int l, int r) {
     48         if (l == r) { sumv[o] = a[l]; tag[o] = 0; return; }
     49         int mid = (l + r) >> 1;
     50         build(lson, l, mid); build(rson, mid+1, r);
     51         pushup(o);
     52     }
     53     void modify(int o, int l, int r, int ql, int qr, int v) {
     54         if (ql <= l && r <= qr) { sumv[o] = (sumv[o] + (LL)v * (r - l + 1)) % P; tag[o] = (tag[o] + v) % P; return; }
     55         pushdown(o, l, r);
     56         int mid = (l + r) >> 1;
     57         if (ql <= mid) modify(lson, l, mid, ql, qr, v);
     58         if (mid < qr) modify(rson, mid+1, r, ql, qr, v);
     59         pushup(o);
     60     }
     61     int query(int o, int l, int r, int ql, int qr) {
     62         if (ql <= l && r <= qr) return sumv[o];
     63         pushdown(o, l, r);
     64         int mid = (l + r) >> 1; LL res = 0;
     65         if (ql <= mid) res += query(lson, l, mid, ql, qr);
     66         if (mid < qr) res += query(rson, mid+1, r, ql, qr);
     67         return res % P;
     68     }
     69 } T;
     70 
     71 //
     72 int son[maxn], link[maxn], mark[maxn], par[maxn], dep[maxn], topf[maxn], st[maxn], en[maxn], cnt = 0;
     73 // son表示结点i的子树大小(包括i),link表示重孩子,mark表示结点i在线段树的位置,par表示父亲结点,dep表示结点i的深度,topf表示i所在的树链的头,st,ed表示子数所在区间。
     74 void dfs1(int u, int fa) {
     75     son[u] = 1; link[u] = u; dep[u] = dep[fa]+1; par[u] = fa;
     76     iter(i, u)
     77         if (e[i].v != fa) {
     78             dfs1(e[i].v, u);
     79             if (son[e[i].v] >= son[link[u]]) link[u] = e[i].v; // 必须写前面!!否则会挂(因为如果有儿子结点就一定会更新,放后面就不行了)
     80             son[u] += son[e[i].v];
     81         }
     82 }
     83 void dfs2(int u, int fa, int head) {
     84     mark[u] = st[u] = ++cnt; topf[u] = head; a[cnt] = val[u];
     85     if (link[u] != u) dfs2(link[u], u, head);
     86     iter(i, u)
     87         if (e[i].v != fa && e[i].v != link[u])
     88             dfs2(e[i].v, u, e[i].v);
     89     en[u] = cnt;
     90 }
     91 #define swap(i, j) i ^= j ^= i ^= j;
     92 void modify_link(int x, int y, int v) {
     93     while (topf[x] != topf[y]) {
     94         if (dep[topf[x]] < dep[topf[y]]) swap(x, y);
     95         T.modify(1, 1, N, mark[topf[x]], mark[x], v);
     96         x = par[topf[x]];
     97     }
     98     if (dep[x] > dep[y]) swap(x, y);
     99     T.modify(1, 1, N, mark[x], mark[y], v);
    100 }
    101 int query_link(int x, int y) {
    102     LL res = 0;
    103     while (topf[x] != topf[y]) {
    104         if (dep[topf[x]] < dep[topf[y]]) swap(x, y);
    105         res += T.query(1, 1, N, mark[topf[x]], mark[x]);
    106         x = par[topf[x]];
    107     }
    108     if (dep[x] > dep[y]) swap(x, y);
    109     return (res + T.query(1, 1, N, mark[x], mark[y])) % P;
    110 }
    111 void modify_tree(int x, int v) { T.modify(1, 1, N, st[x], en[x], v); }
    112 int query_tree(int x) { return T.query(1, 1, N, st[x], en[x]); }
    113 // ###
    114 
    115 int opt, x, y, z;
    116 
    117 int main() {
    118     init();
    119     N = read(), M = read(), R = read(), P = read();
    120     rep(i, 1, N) val[i] = read();
    121     rep(i, 1, N-1) {
    122         x = read(), y = read();
    123         add(x, y); add(y, x);
    124     }
    125     dfs1(R, R); dfs2(R, R, R); T.build(1, 1, N);
    126     rep(i, 1, M) {
    127         opt = read();
    128         if (opt == 1) {
    129             x = read(), y = read(), z = read();
    130             modify_link(x, y, z);
    131         }
    132         else if (opt == 4) {
    133             x = read();
    134             printf("%d
    ", query_tree(x));
    135         } else {
    136             x = read(), y = read();
    137             if (opt == 2) printf("%d
    ", query_link(x, y));
    138             else modify_tree(x, y);
    139         }
    140     }
    141     return 0;
    142 }
  • 相关阅读:
    C语言I博客作业02
    C语言I—2019秋作业01
    C语言I作业10
    C语言I作业09
    C语言I作业08
    C语言I作业07
    C语言I|作业06
    C语言I作业05
    C语言I作业004:第八周作业
    c语言|作业003
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10425927.html
Copyright © 2011-2022 走看看