• NOIP2018——保卫王国


    考场并不知道动态dp这东西。

    考虑$f[i][0]$表示$i$这个位置必须不选

      $f[i][1]$表示$i$这个位置必须选

    显然可以每次$O(n)$来重新dp一次。

    但是我们发现,每次的要求只修改两个位置到LCA的$f$值和$LCA$到根的$f$值。

    考虑每次用矩阵转移,将矩阵弄在边上,将矩阵重载为$min和+$

    然后修改一个点就是一个点到根的路径上的矩阵合并起来,用倍增维护。

    然后同时到LCA的时候不好处理,讨论一下就行了。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define M 100010
      4 #define LL long long
      5 #define inf 1000000000000ll
      6 inline int read() {
      7     char ch = getchar(); int x = 0, f = 1;
      8     while(ch < '0' || ch > '9') {
      9         if(ch == '-') f = -1;
     10         ch = getchar();
     11     }
     12     while('0' <= ch && ch <= '9') {
     13         x = x * 10 + ch - '0';
     14         ch = getchar();
     15     }
     16     return x * f;
     17 }
     18 int p[M];
     19 struct Edge{
     20     int u, v, Next;
     21 } G[M * 2];
     22 int head[M], tot;
     23 inline void add(int u, int v) {
     24     G[++ tot] = (Edge){u, v, head[u]};
     25     head[u] = tot;
     26 }
     27 struct Node{
     28     LL a[2][2];
     29     Node() {
     30         a[0][1] = a[1][0] = a[1][1] = a[0][0] = inf;
     31     }
     32     inline Node operator * (const Node& rhs) const {
     33         Node ret;
     34         for(int i = 0; i <= 1; ++ i) {
     35             for(int j = 0; j <= 1; ++ j) {
     36                 for(int k = 0; k <= 1; ++ k) {
     37                     ret.a[i][j] = min(ret.a[i][j], a[i][k] + rhs.a[k][j]);
     38                 }
     39             }
     40         }
     41         return ret;
     42     }
     43     inline void print() {
     44         printf("%lld %lld
    ", a[0][0], a[0][1]);
     45         printf("%lld %lld
    ", a[1][0], a[1][1]);
     46     }
     47 } g[M][19];
     48 LL f[M][2];
     49 int h[M], ft[M][19];
     50 inline void dfs(int x, int fa) {
     51     h[x] = h[fa] + 1;
     52     ft[x][0] = fa;
     53     for(int i = 1; i <= 18; ++ i) {
     54         ft[x][i] = ft[ft[x][i - 1]][i - 1];
     55     }
     56     f[x][1] = p[x];
     57     for(int i = head[x]; i != -1; i = G[i].Next) {
     58         if(G[i].v == fa) continue;
     59         dfs(G[i].v, x);
     60         f[x][0] += f[G[i].v][1];
     61         f[x][1] += min(f[G[i].v][0], f[G[i].v][1]);
     62     }
     63 }
     64 inline void dfs1(int x, int fa) {
     65     for(int i = head[x]; i != -1; i = G[i].Next) {
     66         if(G[i].v == fa) continue;
     67         dfs1(G[i].v, x);
     68         g[G[i].v][0].a[0][0] = inf;
     69         g[G[i].v][0].a[1][0] = f[x][0] - f[G[i].v][1];
     70         g[G[i].v][0].a[0][1] = f[x][1] - min(f[G[i].v][0], f[G[i].v][1]);
     71         g[G[i].v][0].a[1][1] = f[x][1] - min(f[G[i].v][0], f[G[i].v][1]);
     72     }
     73 }
     74 inline int lca(int x, int y) {
     75     if(h[x] < h[y]) swap(x, y);
     76     int t = h[x] - h[y];
     77     for(int i = 0; i <= 18; ++ i) {
     78         if((1 << i) & t) {
     79             x = ft[x][i];
     80         }
     81     }
     82     if(x == y) return x;
     83     for(int i = 18; i >= 0; -- i) {
     84         if(ft[x][i] != ft[y][i]) {
     85             x = ft[x][i];
     86             y = ft[y][i];
     87         }
     88     }
     89     return ft[x][0];
     90 }
     91 int main() {
     92     int n = read(), m = read();
     93     char s[10]; scanf("%s", s);
     94     for(int i = 1; i <= n; ++ i) {
     95         p[i] = read();
     96     }
     97     memset(head, -1, sizeof(head));
     98     for(int i = 1; i < n; ++ i) {
     99         int u = read(), v = read();
    100         add(u, v), add(v, u);
    101     }
    102     dfs(1, 0);
    103     dfs1(1, 0);
    104     for(int i = 1; i <= 18; ++ i) {
    105         for(int j = 1; j <= n; ++ j) {
    106             if(ft[j][i] != 0) {
    107                 g[j][i] = g[j][i - 1] * g[ft[j][i - 1]][i - 1];
    108             }
    109         }
    110     }
    111     while(m --) {
    112         int x = read(), a = read(), y = read(), b = read();
    113         if(h[x] < h[y]) {
    114             swap(x, y), swap(a, b);
    115         }
    116         int LCA = lca(x, y);
    117         Node A, B;
    118         A.a[0][a] = f[x][a];
    119         B.a[0][b] = f[y][b];
    120         for(int i = 18; i >= 0; -- i) {
    121             if(h[ft[x][i]] > h[LCA]) {
    122                 A = A * g[x][i];
    123                 x = ft[x][i];
    124             }
    125         }
    126         for(int i = 18; i >= 0; -- i) {
    127             if(h[ft[y][i]] > h[LCA]) {
    128                 B = B * g[y][i];
    129                 y = ft[y][i];
    130             }
    131         }
    132         
    133         if(y == LCA) {
    134             A = A * g[x][0];
    135             A.a[0][b ^ 1] = inf;
    136         }
    137         else {
    138             Node C;
    139             C.a[0][0] = f[LCA][0] - f[x][1] - f[y][1] + A.a[0][1] + B.a[0][1];
    140             C.a[0][1] = f[LCA][1] - min(f[x][0], f[x][1]) - min(f[y][0], f[y][1]);
    141             C.a[0][1] += min(A.a[0][0], A.a[0][1]) + min(B.a[0][0], B.a[0][1]);
    142             A = C;
    143         }
    144         x = ft[x][0];
    145         for(int i = 18; i >= 0; -- i) {
    146             if(h[ft[x][i]] >= 1) {
    147                 A = A * g[x][i];
    148                 x = ft[x][i];
    149             } 
    150         }
    151         if(A.a[0][0] == inf && A.a[0][1] == inf) {
    152             puts("-1");
    153         }
    154         else printf("%lld
    ", min(A.a[0][0], A.a[0][1]));
    155     }
    156 }
  • 相关阅读:
    玉米不怕累,宇春最珍贵
    幸福
    谷歌位置搜索 蹩脚结合jquery.ui.gmap
    Resharp Format XML config
    正则表达取得 image src 中值
    一个Gif处理的类库
    使用nuGet管理自己的包
    正则表达式语言 快速参考
    动态加入JS及加入CSS
    检测是一个时间串或一个数字串是否连续
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/10001206.html
Copyright © 2020-2023  润新知