• 洛谷3384树链剖分模板


      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cctype>
      8 #include <climits>
      9 #include <iostream>
     10 #include <iomanip>
     11 #include <algorithm>
     12 #include <string>
     13 #include <sstream>
     14 #include <stack>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <vector>
     19 #include <list>
     20 #include <fstream>
     21 #define ri readint()
     22 #define gc getchar()
     23 #define R(x) scanf("%d", &x)
     24 #define W(x) printf("%d
    ", x)
     25 #define init(a, b) memset(a, b, sizeof(a))
     26 #define rep(i, a, b) for (int i = a; i <= b; i++)
     27 #define irep(i, a, b) for (int i = a; i >= b; i--)
     28 #define ls  p << 1
     29 #define rs    p << 1 | 1
     30 using namespace std;
     31 
     32 typedef double db;
     33 typedef long long ll;
     34 typedef unsigned long long ull;
     35 typedef pair<int, int> P;
     36 const int inf = 0x3f3f3f3f;
     37 const ll INF = 1e18;
     38 
     39 inline int readint() {
     40     int x = 0, s = 1, c = gc;
     41     while (c <= 32)    c = gc;
     42     if (c == '-')    s = -1, c = gc;
     43     for (; isdigit(c); c = gc)
     44         x = x * 10 + c - 48;
     45     return x * s;
     46 }
     47 
     48 const int maxn = 1e5 + 5;
     49 int n, m, root, mod, a[maxn];
     50 int deep[maxn], fa[maxn], size[maxn], son[maxn], top[maxn], id[maxn], rnk[maxn], cnt;
     51 
     52 struct Edge {
     53     int to, nxt;
     54 }e[maxn << 1];
     55 int tot, head[maxn];
     56 
     57 struct Seg {
     58     int l, r, sum, laz;
     59 }t[maxn << 2];
     60 
     61 inline void add(int u, int v) {
     62     e[++tot].to = v, e[tot].nxt = head[u], head[u] = tot; 
     63 }
     64 
     65 inline int len(int p) {
     66     return t[p].r - t[p].l + 1;
     67 }
     68 
     69 inline void push_up(int p) {
     70     t[p].sum = (t[ls].sum + t[rs].sum) % mod;
     71 }
     72 
     73 inline void push_down(int p) {
     74     if (t[p].laz) {
     75         t[ls].laz += t[p].laz;
     76         t[rs].laz += t[p].laz;
     77         t[ls].sum = (t[ls].sum + len(ls) * t[p].laz % mod) % mod;
     78         t[rs].sum = (t[rs].sum + len(rs) * t[p].laz % mod) % mod;
     79         t[p].laz = 0;
     80     }
     81 }
     82 
     83 void build(int l, int r, int p) {
     84     t[p].l = l, t[p].r = r;
     85     if (l == r) {
     86         t[p].laz = 0;
     87         t[p].sum = rnk[l];
     88         return;
     89     }
     90     int mid = (l + r) >> 1;
     91     build(l, mid, ls);
     92     build(mid + 1, r, rs);
     93     push_up(p);
     94 }
     95 
     96 void segupd(int l, int r, int p, int k) {
     97     if (l <= t[p].l && t[p].r <= r) {
     98         t[p].sum = (t[p].sum + len(p) * k % mod) % mod;
     99         t[p].laz += k;
    100         return;
    101     }
    102     int mid = (t[p].l + t[p].r) >> 1;
    103     push_down(p);
    104     if (l <= mid)    segupd(l, r, ls, k);
    105     if (mid < r)    segupd(l, r, rs, k);
    106     push_up(p);
    107 }
    108 
    109 int segask(int l, int r, int p) {
    110     if (l <= t[p].l && t[p].r <= r)    return t[p].sum;
    111     int mid = (t[p].l + t[p].r) >> 1;
    112     int res = 0;
    113     push_down(p);
    114     if (l <= mid)    res = (res + segask(l, r, ls)) % mod;
    115     if (mid < r)    res = (res + segask(l, r, rs)) % mod;
    116     return res;
    117 }
    118 
    119 void dfs1(int u, int f, int depth) {//得到重儿子及一些普通信息
    120     deep[u] = depth;
    121     fa[u] = f;
    122     size[u] = 1;
    123     for (int i = head[u]; i; i = e[i].nxt) {
    124         int v = e[i].to;
    125         if (v == f)    continue;
    126         dfs1(v, u, depth + 1);
    127         if (size[v] > size[son[u]])    son[u] = v;
    128         size[u] += size[v];
    129     }
    130 }
    131 
    132 void dfs2(int u, int topf) {//将重链排列在一起以便线段树维护
    133     id[u] = ++cnt;
    134     rnk[cnt] = a[u];
    135     top[u] = topf;
    136     if (!son[u])    return;
    137     dfs2(son[u], topf);
    138     for (int i = head[u]; i; i = e[i].nxt) {
    139         int v = e[i].to;
    140         if (v != son[u] && v != fa[u])
    141             dfs2(v, v);
    142     }
    143 }
    144 
    145 void Update(int x, int y, int z) {//类似倍增的方式
    146     while (top[x] != top[y]) {
    147         if (deep[top[x]] < deep[top[y]])    swap(x, y);
    148         segupd(id[top[x]], id[x], 1, z);
    149         x = fa[top[x]];
    150     }
    151     if (deep[x] > deep[y])    swap(x, y);
    152     segupd(id[x], id[y], 1, z);
    153 }
    154 
    155 int Query(int x, int y) {
    156     int ans = 0;
    157     while (top[x] != top[y]) {
    158         if (deep[top[x]] < deep[top[y]])    swap(x, y);
    159         ans = (ans + segask(id[top[x]], id[x], 1)) % mod;
    160         x = fa[top[x]];
    161     }
    162     if (deep[x] > deep[y])    swap(x, y);
    163     ans = (ans + segask(id[x], id[y], 1)) % mod;
    164     return ans;
    165 }
    166 
    167 int main() {
    168     n = ri, m = ri, root = ri, mod = ri;
    169     rep(i, 1, n) {
    170         a[i] = ri;
    171         a[i] %= mod;
    172     }
    173     rep(i, 1, n - 1) {
    174         int x = ri, y = ri;
    175         add(x, y);
    176         add(y, x);
    177     }
    178     dfs1(root, 0, 1);
    179     dfs2(root, root);
    180     build(1, n, 1);
    181     
    182     while (m--) {
    183         int op = ri, x, y, z;
    184         if (op == 1) {
    185             x = ri, y = ri, z = ri;
    186             Update(x, y, z % mod);//从x到y的最短路径上的节点都加z
    187         } else if (op == 2) {
    188             x = ri, y = ri;
    189             W(Query(x, y));//查询x到y的最短路节点和
    190         } else if (op == 3) {
    191             x = ri, z = ri;
    192             segupd(id[x], id[x] + size[x] - 1, 1, z % mod);//对x的子树全加z
    193         } else {
    194             x = ri;
    195             W(segask(id[x], id[x] + size[x] - 1, 1));//查询x的子树节点和
    196         }
    197     }
    198     return 0;
    199 }
  • 相关阅读:
    JDK、JRE、JVM的区别联系
    1.1 计算机基础知识 —— 二进制
    java--面试中遇到的各种比较区别
    springMVC 运行流程
    算法--常用排序和查找
    Java面试问题总结
    dpkg:error错误求解:——重复文件触发关注
    memcpy实现
    Palindrome Number
    no matching function for call to 'sort(...),
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10439238.html
Copyright © 2020-2023  润新知