zoukankan      html  css  js  c++  java
  • 树链剖分模板

    洛谷P3384【模板】树链剖分·第一个树剖祭


    题目描述

    如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

    操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

    操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

    操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

    操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

    输入输出格式

    输入格式:

    第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

    接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。

    接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)

    接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:

    操作1: 1 x y z

    操作2: 2 x y

    操作3: 3 x z

    操作4: 4 x

    输出格式:

    输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)


    代码:(感觉自己写的有点长```>_<```······)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int MAX = 100005;
      4 typedef struct Node{
      5     long long val, tag;
      6     int l, r;
      7     Node *rson, *lson;
      8     int len() {return r - l;}
      9     int mid() {return (l + r) >> 1;}
     10     Node(): rson(NULL), lson(NULL), l(0), r(0), val(0), tag(0){}
     11 }node, *pointer;
     12 
     13 int mod;
     14 
     15 class Segment_Tree
     16 {
     17     public:
     18         pointer rt = new Node();
     19         long long a[MAX];
     20     
     21     void PushUp(pointer rt)
     22         {
     23             rt->val = rt->rson->val + rt->lson->val;
     24         }
     25     
     26     void PushDown(pointer rt)
     27         {
     28             if(rt->tag)
     29                 {
     30                     rt->lson->tag += rt->tag;
     31                     rt->rson->tag += rt->tag;
     32                     rt->lson->val += rt->tag * rt->lson->len();
     33                     rt->rson->val += rt->tag * rt->rson->len();
     34                     rt->tag = 0;
     35                 }
     36         }
     37     
     38     void Build(pointer rt,int l, int r)
     39         {
     40             rt->l = l;
     41             rt->r = r;
     42             if(l + 1 == r)
     43                 {
     44                     rt->val = a[l];
     45                     //rt->pos = l;
     46                     rt->rson = NULL;
     47                     rt->lson = NULL;
     48                     return ;
     49                 }
     50             rt->rson = new Node();
     51             rt->lson = new Node();
     52             Build(rt->lson, l, rt->mid());
     53             Build(rt->rson, rt->mid(), r);
     54             PushUp(rt); 
     55         }
     56         
     57     void UpData(pointer rt, int L, int R, int k)
     58         {
     59             if(L <= rt->l && rt->r <= R)
     60                 {
     61                     rt->val += k * rt->len();
     62                     rt->tag += k;
     63                 }
     64             else
     65                 {
     66                     if(rt->tag != 0)    PushDown(rt);
     67                     if(L < rt->mid())    UpData(rt->lson, L, R, k);
     68                     if(R > rt->mid())     UpData(rt->rson, L, R, k);
     69                     PushUp(rt);
     70                 }
     71         }
     72         
     73     long long Query(pointer rt, int L, int R)
     74         {
     75             if(L <= rt->l && rt->r <= R)    return rt->val;
     76             else
     77                 {
     78                     if(rt->tag != 0)    PushDown(rt);
     79                     long long ret = 0;
     80                     if(L < rt->mid())    ret += Query(rt->lson, L, R);
     81                     if(R > rt->mid()) ret += Query(rt->rson, L, R);
     82                     return ret;
     83                 }
     84         }
     85 };
     86 
     87 class Tree_Chain_Division
     88 {
     89 private:
     90     int Head[MAX], Next[MAX << 1], To[MAX << 1], edgenum = 0;
     91     int size[MAX], Hson[MAX], Father[MAX], Deep[MAX], pos[MAX];
     92     int tid[MAX], ti = 0, top[MAX];
     93     Segment_Tree tree;
     94 
     95     void First_Dfs(int u, int fa)
     96         {
     97             size[u] = 1, Father[u] = fa;
     98             for(int i = Head[u]; i != -1; i = Next[i])
     99                 {
    100                     int v = To[i];
    101                     if(v == fa) continue;
    102                     Deep[v] = Deep[u] + 1;
    103                     First_Dfs(v, u);
    104                     size[u] += size[v];
    105                     if(size[v] > size[Hson[u]] || Hson[u] == 0)    Hson[u] = v;
    106                 }
    107             return;
    108         }
    109 
    110     void Second_Dfs(int u, int anc)
    111         {
    112             top[u] = anc, tid[u] = ++ti, pos[ti] = u;
    113             if(Hson[u] == 0)    return;
    114             Second_Dfs(Hson[u], anc);
    115             for(int i = Head[u]; i != -1; i = Next[i])
    116                 {
    117                     int v = To[i];
    118                     if(Father[u] == v || Hson[u] == v)  continue;
    119                     Second_Dfs(v, v);
    120                 }
    121             return ;
    122         }
    123 
    124 public:
    125     int a[MAX];
    126     
    127     void init()
    128         {
    129             memset(Head, -1, sizeof(Head));
    130         }
    131 
    132     void Add_edge(int from, int to)
    133         {
    134             Next[++ edgenum] = Head[from];
    135             To[edgenum] = to;
    136             Head[from] = edgenum;
    137         }
    138 
    139     void Chain_Division(int root, int n)
    140         {
    141             Deep[root] = 1;
    142             First_Dfs(root, 0);
    143             Second_Dfs(root, root);
    144             for(int i = 1; i <= n; ++ i)    tree.a[i] = a[pos[i]];
    145             tree.Build(tree.rt, 1, n + 1);
    146             return;
    147         }
    148 
    149     int Get_LCA(int x, int y)
    150         {
    151             int Father_x = top[x], Father_y = top[y];
    152             for(;Father_x != Father_y;)
    153                 {
    154                     if(Deep[Father_x] < Deep[Father_y])
    155                         swap(Father_y, Father_x), swap(x, y);
    156                     x = Father[Father_x], Father_x = top[x];
    157                 }
    158             return Deep[x] < Deep[y] ? x : y;
    159         }
    160 
    161     void Chai_Add(int x, int y, int w) //x y z 表示将树从x到y结点最短路径上所有节点的值都加上w
    162         {
    163             int Father_x = top[x], Father_y = top[y];
    164             for(;Father_x != Father_y;)
    165                 {
    166                     if(Deep[Father_x] < Deep[Father_y])
    167                         swap(Father_y, Father_x), swap(x, y);
    168                     tree.UpData(tree.rt, tid[Father_x], tid[x] + 1, w);
    169                     x = Father[Father_x], Father_x = top[x];
    170                 }
    171              if(Deep[x] < Deep[y]) swap(x, y);
    172              tree.UpData(tree.rt, tid[y], tid[x] + 1, w);
    173              return ;
    174         }
    175 
    176     long long Chai_Query(int x, int y)  //x y 表示求树从x到y结点最短路径上所有节点的值之和
    177         {
    178             long long ans = 0;
    179             int Father_x = top[x], Father_y = top[y];
    180             for(;Father_x != Father_y;)
    181                 {
    182                     if(Deep[Father_x] < Deep[Father_y])
    183                         swap(Father_y, Father_x), swap(x, y);
    184                     ans = (ans + tree.Query(tree.rt, tid[Father_x], tid[x] + 1)) % mod;
    185                     x = Father[Father_x], Father_x = top[x];
    186                 }
    187             if(Deep[x] < Deep[y])  swap(x, y);
    188             ans = (ans + tree.Query(tree.rt, tid[y], tid[x] + 1)) % mod;
    189             return ans;
    190         }
    191 
    192     void Tree_Add(int x, int w) //x w 表示将以x为根节点的子树内所有节点值都加上w
    193         {
    194             tree.UpData(tree.rt, tid[x], tid[x] + size[x], w);
    195             return;
    196         }
    197 
    198     long long Tree_Query(int x)  //x 表示求以x为根节点的子树内所有节点值之和
    199         {
    200             return tree.Query(tree.rt, tid[x], tid[x] + size[x]) % mod; 
    201         }
    202 };
    203 
    204 inline int Qread()
    205     {
    206         int x = 0, w = 0; char ch = getchar();
    207         for(;!isdigit(ch);w |= (ch == '-'), ch = getchar());
    208         for(;isdigit(ch); x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar());
    209         return w ? -x : x;
    210     }
    211 
    212 Tree_Chain_Division division;
    213 int main()
    214 {
    215 //    freopen("sp.in", "r", stdin);
    216 //    freopen("sp.out", "w", stdout);
    217     
    218     int x, y, opt, z, n = Qread(), m = Qread(), root = Qread(); mod = Qread();
    219     for(int i = 1; i <= n; ++ i) division.a[i] = Qread();
    220     division.init();
    221     for(int i = 1; i <  n; ++ i) 
    222         {
    223             x = Qread(), y = Qread();
    224             division.Add_edge(x, y), division.Add_edge(y, x);
    225         }
    226     division.Chain_Division(root, n);
    227     for(int i = 1; i <= m; ++ i)
    228         {
    229             opt = Qread();
    230             switch(opt)
    231             {
    232                 case 1: x = Qread(), y = Qread(), z = Qread(); division.Chai_Add(x, y, z); break;
    233                 case 2: x = Qread(), y = Qread(); printf("%lld
    ", division.Chai_Query(x, y)); break;
    234                 case 3: x = Qread(), y = Qread(); division.Tree_Add(x, y); break;
    235                 case 4: x = Qread(); printf("%lld
    ", division.Tree_Query(x)); break;
    236             }
    237         }
    238     return 0;
    239 }
  • 相关阅读:
    马尔科夫模型
    统计自然语言处理(第2版)目录
    linux运维学习笔记随想
    Redis 入门:(1)Linux下使用
    TextRank算法原理及应用示例
    实验十 团队作业6:团队项目用户验收&Beta冲刺
    关于tensorflow
    实验九 团队作业6:团队项目编码&Alpha冲刺
    实验八 团队作业4—团队项目需求建模与系统设计
    实验七 团队作业3:团队项目需求分析与原型设计
  • 原文地址:https://www.cnblogs.com/2020pengxiyue/p/9296579.html
Copyright © 2011-2022 走看看