zoukankan      html  css  js  c++  java
  • Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)

    题目链接:

      Hdu 3966 Aragorn's Story

    题目描述:

      给出一个树,每个节点都有一个权值,有三种操作:

      1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x;

      2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x;

      3:(Q, x) 查询节点x的权值为多少?

    解题思路:

      可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 const int maxn = 50010;
      8 #define lson(x) 2*x+1
      9 #define rson(x) 2*x+2
     10 
     11 struct e
     12 {
     13     int to, next;
     14 }edge[maxn*2];
     15 struct node
     16 {
     17     int l, r, val, x;
     18     int Mid ()
     19     {
     20         return (l+r)/2;
     21     }
     22 }tree[maxn*4];
     23 int val[maxn], x[maxn], deep[maxn], size[maxn], tot, num;
     24 int son[maxn], top[maxn], id[maxn], head[maxn], fa[maxn];
     25 
     26 void init ()
     27 {
     28     num = tot =0;
     29     memset (head, -1, sizeof(head));
     30 }
     31 
     32 void Add (int from, int to)
     33 {
     34     edge[tot].to = to;
     35     edge[tot].next = head[from];
     36     head[from] = tot ++;
     37 }
     38 
     39 //找重边
     40 void dfs1 (int u, int f, int dep)
     41 {
     42     son[u] = 0;
     43     fa[u] = f;
     44     deep[u] = dep;
     45     size[u] = 1;
     46     
     47     for (int i=head[u]; i!=-1; i=edge[i].next)
     48     {
     49         int v = edge[i].to;
     50         if (v == f) continue;
     51         dfs1 (v, u, dep+1);
     52         size[u] += size[v];
     53         if (size[son[u]] < size[v])
     54             son[u] = v;
     55     }
     56 }
     57 
     58 //重边连接成重链
     59 void dfs2 (int u, int tp)
     60 {
     61     top[u] = tp;
     62     id[u] = ++num;
     63     if (son[u]) dfs2 (son[u], tp);
     64     
     65     for (int i=head[u]; i!=-1; i=edge[i].next)
     66     {
     67         int v = edge[i].to;
     68         if (v == fa[u] || v == son[u]) continue;
     69         dfs2 (v, v);
     70     }
     71 }
     72 
     73 //区间更新线段树,向下一层更新
     74 void pushup (int x)
     75 {
     76     tree[lson(x)].x += tree[x].x;
     77     tree[rson(x)].x += tree[x].x;
     78     tree[lson(x)].val +=  tree[x].x;
     79     tree[rson(x)].val +=  tree[x].x;
     80     tree[x].x = 0;
     81 }
     82 
     83 void build (int root, int l, int r)
     84 {
     85     tree[root].l = l;
     86     tree[root].r = r;
     87     tree[root].x = tree[root].val = 0;
     88     
     89     if (l == r)
     90     {
     91         tree[root].val = val[l];
     92         return ;
     93     }
     94     
     95     build (lson(root), l, tree[root].Mid());
     96     build (rson(root), tree[root].Mid()+1, r);
     97 }
     98 
     99 void updata (int root, int l, int r, int x)
    100 {
    101     if (tree[root].l == l && r == tree[root].r)
    102     {
    103         tree[root].val +=  x;
    104         tree[root].x += x;
    105         return ;
    106     }
    107     
    108     if (tree[root].x)
    109         pushup (root);
    110         
    111     if (r <= tree[root].Mid())
    112         updata (lson(root), l, r, x);
    113     else if (tree[root].Mid() < l)
    114         updata (rson(root), l, r, x);
    115     else
    116     {
    117         updata (lson(root), l, tree[root].Mid(), x);
    118         updata (rson(root), tree[root].Mid()+1, r, x);
    119     }
    120 }
    121 
    122 int query (int root, int x)
    123 {
    124     if (tree[root].l == tree[root].r && tree[root].l == x)
    125         return tree[root].val;
    126         
    127     if (tree[root].x)
    128         pushup (root);
    129         
    130     if (x <= tree[root].Mid())
    131         query (lson(root), x);
    132     else
    133         query (rson(root), x);
    134 }
    135 
    136 //处理节点u,v
    137 void alter (int u, int v,int x)
    138 {
    139     int tp1 = top [u];
    140     int tp2 = top [v];
    141     
    142     while (tp1 != tp2)
    143     {//两个节点不在同一个重链上
    144         if (deep[tp1] < deep[tp2])
    145         {
    146             swap (tp1, tp2);
    147             swap (u, v);
    148         }//deep深的重链上升
    149         
    150         updata (0, id[tp1], id[u], x);
    151         u = fa[tp1];
    152         tp1 = top[u];
    153     }
    154     
    155     //在同一条重链上
    156     if (deep[u] > deep[v])
    157         swap (u, v);
    158     updata (0, id[u], id[v], x);
    159 
    160 }
    161 
    162 int main ()
    163 {
    164     int n, m, q;
    165     
    166     while (scanf ("%d %d %d", &n, &m, &q) != EOF)
    167     {
    168         init ();
    169         for (int i=1; i<=n; i++)
    170             scanf ("%d", &x[i]);
    171         for (int i=0; i<m; i++)
    172         {
    173             int x, y;
    174             scanf ("%d %d", &x, &y);
    175             Add (x, y);
    176             Add (y, x);
    177         }
    178         
    179         dfs1 (1, 0, 1);
    180         dfs2 (1, 1);
    181         
    182         //hash原来节点
    183         for (int i=1; i<=n; i++)
    184             val[id[i]] = x[i];
    185         build (0, 1, n);
    186         
    187         while (q --)
    188         {
    189             char str[10];
    190             int l, r, x;
    191             scanf ("%s", str);
    192             
    193             if (str[0] == 'Q')
    194             {
    195                 scanf ("%d", &x);
    196                 printf ("%d
    ", query (0, id[x]));
    197             }
    198             else if (str[0] == 'I')
    199             {
    200                 scanf ("%d %d %d", &l, &r, &x);
    201                 alter (l, r, x);
    202             }
    203             else
    204             {
    205                 scanf ("%d %d %d", &l, &r, &x);
    206                 alter (l, r, -x);
    207             }
    208             
    209         }
    210     }
    211     return 0;
    212 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    c# 反射取其他项目的资源文件
    【分享】免费建立自己的站点
    c# 自定义类型的DataBindings
    ListView 多行拖拽排序
    linq to sql之组装where条件下的'或'语句
    dotfuscator使用方法
    orderBy 传入属性的字符串
    WCF数据交互时长度超过8192
    ASP.net中aspx与cs函数的互调
    c# 读取excel数据的两种方法
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4802177.html
Copyright © 2011-2022 走看看