zoukankan      html  css  js  c++  java
  • [luoguP3258] [JLOI2014]松鼠的新家(lca + 树上差分)

    传送门

    需要把一条路径上除了终点外的所有数都 + 1,

    比如,给路径 s - t 上的权值 + 1,可以先求 x = lca(s,t)

    类似数列上差分的思路,可以给 s 和 f[t] 的权值 + 1,给 x 和 f[x] 的权值 - 1

    最后统计以每个节点为根的子树的和,则每个节点的权值就是子树的权值。

    ——代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 
     5 const int MAXN = 300001;
     6 int n, cnt;
     7 int a[MAXN], head[MAXN], to[MAXN << 1], next[MAXN << 1], deep[MAXN], f[MAXN][21], val[MAXN];
     8 
     9 inline int read()
    10 {
    11     int x = 0, f = 1;
    12     char c = getchar();
    13     for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    14     for(; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    15     return x * f;
    16 }
    17 
    18 inline void add(int x, int y)
    19 {
    20     to[cnt] = y;
    21     next[cnt] = head[x];
    22     head[x] = cnt++;
    23 }
    24 
    25 inline void swap(int &x, int &y) { x ^= y ^= x ^= y; }
    26 
    27 inline void dfs(int u)
    28 {
    29     int i, v;
    30     deep[u] = deep[f[u][0]] + 1;
    31     for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
    32     for(i = head[u]; i != -1; i = next[i])
    33     {
    34         v = to[i];
    35         if(!deep[v]) f[v][0] = u, dfs(v);
    36     }
    37 }
    38 
    39 inline int lca(int x, int y)
    40 {
    41     int i;
    42     if(deep[x] < deep[y]) swap(x, y);
    43     for(i = 20; i >= 0; i--)
    44         if(deep[f[x][i]] >= deep[y])
    45             x = f[x][i];
    46     if(x == y) return x;
    47     for(i = 20; i >= 0; i--)
    48         if(f[x][i] != f[y][i])
    49             x = f[x][i], y = f[y][i];
    50     return f[x][0];
    51 }
    52 
    53 inline void dfs1(int u)
    54 {
    55     int i, v;
    56     for(i = head[u]; i != -1; i = next[i])
    57     {
    58         v = to[i];
    59         if(v != f[u][0]) dfs1(v), val[u] += val[v];
    60     }
    61 }
    62 
    63 int main()
    64 {
    65     int i, x, y, z;
    66     n = read();
    67     memset(head, -1, sizeof(head));
    68     for(i = 1; i <= n; i++) a[i] = read();
    69     for(i = 1; i < n; i++)
    70     {
    71         x = read();
    72         y = read();
    73         add(x, y);
    74         add(y, x);
    75     }
    76     dfs(1);
    77     for(i = 2; i <= n; i++)
    78     {
    79         x = a[i - 1];
    80         y = a[i];
    81         z = lca(x, y);
    82         val[z]--, val[f[z][0]]--;
    83         val[x]++, val[f[y][0]]++;
    84     }
    85     dfs1(1);
    86     for(i = 1; i <= n; i++) printf("%d
    ", val[i]);
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    《Centos服务器版安装教程》
    从CentOS官网下载系统镜像详细教程
    一键LNMP文件
    Centos 7 ip地址
    cmd常用命令
    bat命令
    JAVA学习资源整理
    DevOps 高效 shell 命令
    编程范式:命令式编程(Imperative)、声明式编程(Declarative)和函数式编程(Functional)
    Java 中的函数式编程(Functional Programming):Lambda 初识
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6809815.html
Copyright © 2011-2022 走看看