• FZU2082


    树链剖分后要处理的是边的权值,而不是点的权值,但是只要边权下放到点,就可以了

    如图

    但是问题是,求图4->5路径的权值之和, 那么就会把点3给算进去

    那么就要减去,

    或者干脆不加进去

    有两种方法

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #include <string>
     12 #include <math.h>
     13 using namespace std;
     14 #pragma warning(disable:4996)
     15 #pragma comment(linker, "/STACK:1024000000,1024000000")
     16 typedef long long LL;                   
     17 const int INF = 1<<30;
     18 /*
     19 12 1
     20 1 2 1
     21 2 3 1
     22 3 4 1
     23 4 5 1
     24 5 11 1
     25 11 12 1
     26 1 6 1
     27 6 7 1
     28 7 8 1
     29 6 9 1
     30 6 10 1
     31 1 9 10
     32 */
     33 const int N = 50000 + 10;
     34 vector<int> g[N];
     35 int size[N], son[N], fa[N], depth[N], top[N], w[N], num, ra[N];
     36 LL tree[N*4];
     37 int edge[N][3];
     38 int h[N];
     39 void dfs(int u)
     40 {
     41     size[u] = 1;
     42     son[u] = 0;
     43     for (int i = 0; i < g[u].size(); ++i)
     44     {
     45         int v = g[u][i];
     46         if (v != fa[u])
     47         {
     48             fa[v] = u;
     49             depth[v] = depth[u] + 1;
     50             dfs(v);
     51             size[u] += size[v];
     52             if (size[v] > size[son[u]])
     53                 son[u] = v;
     54         }
     55     }
     56 }
     57 
     58 void dfs2(int u, int tp)
     59 {
     60     w[u] = ++num;
     61     ra[num] = u;
     62     top[u] = tp;
     63     if (son[u] != 0)
     64         dfs2(son[u], top[u]);
     65     for (int i = 0; i < g[u].size(); ++i)
     66     {
     67         int v = g[u][i];
     68         if (v != fa[u] && v != son[u])
     69             dfs2(v, v);
     70     }
     71     
     72 }
     73 void pushUp(int rt)
     74 {
     75     tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
     76 }
     77 void update(int l, int r, int rt, int pos, int val)
     78 {
     79     if (l == r)
     80     {
     81         tree[rt] = val;
     82         return;
     83     }
     84     int mid = (l + r) >> 1;
     85     if (pos <= mid)
     86         update(l, mid, rt << 1, pos, val);
     87     else
     88         update(mid + 1, r, rt << 1 | 1, pos, val);
     89     pushUp(rt);
     90 }
     91 
     92 LL ans;
     93 void query(int l, int r, int rt, int L, int R)
     94 {
     95     if (L <= l&&R >= r)
     96     {
     97         ans += tree[rt];
     98         return;
     99     }
    100     int mid = (l + r) >> 1;
    101     if (L <= mid)
    102         query(l, mid, rt << 1, L, R);
    103     if (R > mid)
    104         query(mid + 1, r, rt << 1 | 1, L, R);
    105 }
    106 int main()
    107 {
    108     int n, m, a, b, c;
    109     while (scanf("%d%d", &n, &m) != EOF)
    110     {
    111         memset(tree, 0, sizeof(tree));
    112         for (int i = 1; i <= n; ++i)
    113             g[i].clear();
    114         num = 0;
    115         for (int i = 1; i < n; ++i)
    116         {
    117             scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]);
    118             g[edge[i][0]].push_back(edge[i][1]);
    119             g[edge[i][1]].push_back(edge[i][0]);
    120         }
    121         fa[1] = depth[1] = 0;
    122         dfs(1);
    123         dfs2(1, 1);
    124         for (int i = 1; i < n; ++i)
    125         {
    126             if (depth[edge[i][0]] > depth[edge[i][1]])
    127                 swap(edge[i][0], edge[i][1]);
    128             h[edge[i][1]] = edge[i][2];
    129             update(1, n, 1, w[edge[i][1]], edge[i][2]);
    130         }
    131         while (m--)
    132         {
    133             scanf("%d%d%d", &a, &b, &c);
    134             if (a == 0)
    135             {
    136                 if (depth[edge[b][0]] > depth[edge[b][1]])
    137                     swap(edge[b][0], edge[b][1]);
    138                 update(1, n, 1, w[edge[b][1]], c);
    139                 h[edge[b][1]] = c;
    140             }
    141             else
    142             {
    143                 ans = 0;
    144                 while (top[b] != top[c])
    145                 {
    146                     if (depth[top[b]] < depth[top[c]])
    147                         swap(b, c);
    148                     query(1, n, 1, w[top[b]], w[b]);
    149                     b = fa[top[b]];
    150                 }
    151                 //b和c一定是在一条链上
    152                 if (depth[b]>depth[c])
    153                     swap(b, c);
    154                 
    155                 
    156                 //如果b有父亲,那么就有边下放到它,多加了这个点,要减去
    157                 query(1, n, 1, w[b], w[c]);
    158                 if (fa[b] != 0)
    159                     ans -= h[b];
    160                 /*
    161                 如果b,c是在一条重链上, 那么询问w[son[b]] 到w[c]
    162                 那么就没有加到点b
    163                 否则,b,c就是指向同一点,那么w[son[b]] > w[c] , 询问是不会增加任何值的
    164                 query(1, n, 1, w[son[b]], w[c]);
    165                 */
    166                 printf("%lld
    ", ans);
    167             }
    168         }
    169     }
    170     return 0;
    171 }
    View Code
  • 相关阅读:
    codeforce 272B Dima and Sequence
    Codeforce 270D Greenhouse Effect
    codeforce 270C Magical Boxes
    codeforce 270B Multithreading
    图论--Dijkstra算法总结
    图论--(技巧)超级源点与超级汇点
    图论--Floyd总结
    ZOJ 3932 Handshakes
    ZOJ 3932 Deque and Balls
    ZOJ 3927 Programming Ability Test
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4623356.html
Copyright © 2020-2023  润新知