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

    参考博客:https://www.cnblogs.com/George1994/p/7821357.html

      模板题:HDU 3966 Aragorn's Story

      给一棵树每个点有权值,三种操作,一是给两个点和一个值U, V,K,U~V这条路径上所有点+K,二是U~K这条路径上所有点权值-K,三是查询某点U的权值为多少。先写着树链剖分  

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <vector>
      5 #include <queue>
      6 #include <math.h>
      7 #include <string>
      8 #include <algorithm>
      9 #include <time.h>
     10 
     11 #define SIGMA_SIZE 26
     12 #define lson rt<<1
     13 #define rson rt<<1|1
     14 #define lowbit(x) (x&-x)
     15 #define foe(i, a, b) for(int i=a; i<=b; i++)
     16 #define fo(i, a, b) for(int i = a; i < b; i++);
     17 #pragma warning ( disable : 4996 )
     18 #pragma comment(linker, "/STACK:1024000000,1024000000")
     19 
     20 using namespace std;
     21 typedef long long LL;
     22 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
     23 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
     24 inline LL lgcd( LL a, LL b )   { return b==0?a:lgcd(b,a%b); }
     25 inline LL llcm( LL a, LL b )   { return a/lgcd(a,b)*b; }  //a*b = gcd*lcm
     26 inline int Max(int a,int b)    { return a>b?a:b; }
     27 inline int Min(int a,int b)       { return a>b?b:a; }
     28 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     29 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     30 const LL INF = 0x3f3f3f3f3f3f3f3f;
     31 const LL mod  = 1000000007;
     32 const double eps = 1e-8;
     33 const int inf  = 0x3f3f3f3f;
     34 const int maxk = 1e6+5;
     35 const int maxn = 5e4+5;
     36 
     37 int N, M, Q, tim;
     38 int cnt;
     39 int linjie[maxn];
     40 int sum[maxn<<2], lazy[maxn<<2];
     41 int siz[maxn]; //以i为根节点 它的子树的节点个数
     42 int top[maxn]; //当前节点所在链的顶端节点编号
     43 int son[maxn]; //重儿子编号
     44 int faz[maxn]; //当前节点的父亲节点
     45 int dep[maxn]; //深度,
     46 int tid[maxn]; //树中每个节点剖分以后的新编号(dfs执行顺序)
     47 int rnk[maxn]; //当前节点在树中的位置
     48 struct node {
     49     int to, next, val; 
     50 }pp[2*maxn];
     51 
     52 void addedge(int u, int v)
     53 { pp[cnt].to = v; pp[cnt].next = linjie[u]; linjie[u] = cnt++; }
     54 
     55 //第一次dfs更新了dep,faz,siz,son数组
     56 void dfs_1(int u, int fa, int d)
     57 {
     58     dep[u] = d;
     59     faz[u] = fa;
     60     siz[u] = 1;
     61     for ( int i = linjie[u]; ~i; i = pp[i].next)
     62     {
     63         int v = pp[i].to;
     64         if ( v != faz[u] )
     65         {
     66             dfs_1(v, u, d+1);
     67             // 收敛的时候将当前结点的siz加上子结点的siz
     68             siz[u] += siz[v];
     69             // 如果没有设置过重结点son或者子结点v的siz大于之前记录的重结点son,则进行更新
     70             if (son[u] == -1 || siz[v] > siz[son[u]])
     71                 son[u] = v;
     72         }
     73     }
     74 }
     75 
     76 void dfs_2(int u, int tp)
     77 {
     78     top[u] = tp;        // 设置当前结点的起点为tP
     79     tid[u] = ++tim;        // 设置当前结点的dfs执行序号
     80     rnk[tid[u]] = u;    // 设置dfs序号对应成当前结点
     81 
     82     // 如果当前结点没有处在重链上,则不处理
     83     if (son[u] == -1) return;
     84     // 将这条重链上的所有的结点都设置成起始的重结点
     85     dfs_2(son[u], tp);
     86 
     87     for ( int i = linjie[u]; ~i; i = pp[i].next )
     88     {
     89         // 如果连接结点不是当前结点的重子结点并且也不是u的父亲结点,
     90         // 则将其的top设置成自己,进一步递归
     91         int v = pp[i].to;
     92         if (v != son[u] && v != faz[u])
     93             dfs_2(v, v);
     94     }
     95 }
     96 
     97 void pushUp(int rt)
     98 { sum[rt] = Max(sum[lson], sum[rson]); }
     99 
    100 void pushDown(int rt, int ln, int rn)
    101 {
    102     if (lazy[rt])
    103     {
    104         lazy[lson] += lazy[rt];
    105         lazy[rson] += lazy[rt];
    106 
    107         sum[lson] += ln*lazy[rt];
    108         sum[rson] += rn*lazy[rt];
    109 
    110         lazy[rt] = 0;
    111     }
    112 }
    113 
    114 void build(int rt, int L, int R)
    115 {
    116     lazy[rt] = 0;
    117     if ( L == R )
    118     {
    119         //L是dfs遍历顺序编号,rnk[L]是原来的点的编号
    120         sum[rt] = pp[rnk[L]].val;
    121         return;
    122     }
    123 
    124     int mid = (L+R)>>1;
    125     build(lson, L, mid);
    126     build(rson, mid+1, R);
    127     pushUp(rt);
    128 }
    129 
    130 void update(int rt, int L, int R, int lhs, int rhs, int C)
    131 {
    132     if ( lhs <= L && rhs >= R )
    133     {
    134         lazy[rt] += C;
    135         sum[rt] += C*(R-L+1);
    136         return;
    137     }
    138 
    139     int mid = (L+R)>>1;
    140     pushDown(rt, mid-L+1, R-mid);
    141     if ( lhs <= mid ) update(lson, L, mid, lhs, rhs, C);
    142     if ( rhs >  mid ) update(rson, mid+1, R, lhs, rhs, C);
    143     pushUp(rt);
    144 }
    145 
    146 int query(int rt, int L, int R, int V)
    147 {
    148     if ( L == R )
    149         return sum[rt];
    150 
    151     int tmp = -1, mid = (L+R)>>1;
    152     pushDown(rt, mid-L+1, R-mid);
    153     if ( V <= mid ) tmp = query(lson, L, mid, V);
    154     else tmp = query(rson, mid+1, R, V);
    155 
    156     pushUp(rt);
    157     return tmp;
    158 }
    159 
    160 void change(int x, int y, int val)
    161 {
    162     while (top[x] != top[y])
    163     {
    164         //x作为找深度深的那一个节点
    165         if (dep[top[x]] < dep[top[y]]) swap(x, y);
    166         //将x作为一个区间的结尾,top[x]作为一个区间的起始
    167         update(1, 1, N, tid[top[x]], tid[x], val);
    168         //跳到更上层的链
    169         x = faz[top[x]];        
    170     }
    171 
    172     //直到x和y是在同一条链上
    173     if (dep[x] > dep[y]) swap(x, y);
    174     update(1, 1, N, tid[x], tid[y], val);
    175 }
    176 
    177 void init()
    178 {
    179     tim = cnt = 0;
    180     memset(linjie, -1, sizeof(linjie));
    181     memset(son, -1, sizeof(son));
    182 
    183     int x, y;
    184     foe(i, 1, N)
    185         scanf("%d", &pp[i].val);
    186     foe(i, 1, M)
    187     {
    188         scanf("%d %d", &x, &y);
    189         addedge(x, y);
    190         addedge(y, x);
    191     }
    192 
    193     //父节点是0, 深度为0
    194     dfs_1(1, 0, 0);
    195     dfs_2(1, 1);
    196     build(1, 1, N);
    197 }
    198 
    199 
    200 int main()
    201 {
    202     while ( ~scanf("%d %d %d", &N, &M, &Q) )
    203     {
    204         init();
    205 
    206         char str[2];
    207         int x, y, d;
    208         while (Q--)
    209         {
    210             scanf("%s", str);
    211             if (str[0] == 'I') {
    212                 scanf("%d %d %d", &x, &y, &d);
    213                 change(x, y, d);
    214             }
    215             else if (str[0] == 'D') {
    216                 scanf("%d %d %d", &x, &y, &d);
    217                 change(x, y, -d);
    218             }
    219             else {
    220                 scanf("%d", &d);
    221                 printf("%d
    ", query(1, 1, N, tid[d]));
    222             }
    223         }
    224     }
    225     return 0;
    226 }
    View Code
  • 相关阅读:
    web服务器-Apache
    nginx优化
    nginx下载限速
    nginx-URL重写
    HDU 5358 First One 求和(序列求和,优化)
    HDU 5360 Hiking 登山 (优先队列,排序)
    HDU 5353 Average 糖果分配(模拟,图)
    UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。
    HDU 5348 MZL's endless loop 给边定向(欧拉回路,最大流)
    HDU 5344 MZL's xor (水题)
  • 原文地址:https://www.cnblogs.com/chaoswr/p/9362312.html
Copyright © 2011-2022 走看看