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\n", 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 }
posted @ 2015-09-11 21:51  罗茜  阅读(176)  评论(0编辑  收藏  举报