HDU 3966 RE 树链剖分 Aragorn's Story

给一棵点带权的图

有这样一个操作:

  • 使树上某一条路径所有点权值增减

每次询问某个点现在的权值。

树链剖分完以后,就是线段树的成段更新了。

这题感觉A不了了,无限RE,手动开栈也没卵用。

还是把我辛辛苦苦写的代码贴一下吧。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 using namespace std;
  7
  8 const int maxn = 50000 + 10;
  9 const int INF = 0x3f3f3f3f;
 10
 11 void scan(int& x)
 12 {
 13     x = 0;
 14     bool flag = false;
 15     char c = ‘ ‘;
 16     while(c != ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar();
 17     if(c == ‘-‘) { flag = true; c = getchar(); }
 18     while(c >= ‘0‘ && c <= ‘9‘) { x = x * 10 + c - ‘0‘; c = getchar(); }
 19     if(flag) x = -x;
 20 }
 21
 22 int n, m, Q;
 23
 24 vector<int> G[maxn];
 25 int val[maxn];
 26
 27 int tot;
 28 int L[maxn];
 29 int fa[maxn];
 30 int id[maxn];
 31 int top[maxn];
 32 int sz[maxn];
 33 int son[maxn];
 34
 35 void dfs(int u)
 36 {
 37     sz[u] = 1;
 38     son[u] = 0;
 39     for(int i = 0; i < G[u].size(); i++)
 40     {
 41         int v = G[u][i];
 42         if(v == fa[u]) continue;
 43         fa[v] = u;
 44         L[v] = L[u] + 1;
 45         dfs(v);
 46         sz[u] += sz[v];
 47         if(sz[v] > sz[son[u]]) son[u] = v;
 48     }
 49 }
 50
 51 void dfs2(int u, int tp)
 52 {
 53     top[u] = tp;
 54     id[u] = ++tot;
 55     if(son[u]) dfs2(son[u], tp);
 56     for(int i = 0; i < G[u].size(); i++)
 57     {
 58         int v = G[u][i];
 59         if(v == fa[u] || v == son[u]) continue;
 60         dfs2(v, v);
 61     }
 62 }
 63
 64 int vv;
 65 int add[maxn << 2];
 66
 67 void update(int o, int L, int R, int qL, int qR)
 68 {
 69     if(qR < L || qL > R) return ;
 70     if(qL <= L && R <= qR) { add[o] += vv; return ; }
 71     int M = (L + R) / 2;
 72     update(o<<1, L, M, qL, qR);
 73     update(o<<1|1, M+1, R, qL, qR);
 74 }
 75
 76 int query(int o, int L, int R, int p)
 77 {
 78     if(L == R) return add[o];
 79     int M = (L + R) / 2;
 80     add[o<<1] += add[o];
 81     add[o<<1|1] += add[o];
 82     add[o] = 0;
 83     if(p <= M) return query(o<<1, L, M, p);
 84     return query(o<<1|1, M+1, R, p);
 85 }
 86
 87 void Update(int u, int v)
 88 {
 89     int t1 = top[u], t2 = top[v];
 90     while(t1 != t2)
 91     {
 92         if(L[t1] < L[t2]) { swap(t1, t2); swap(u, v); }
 93         update(1, 1, tot, id[t1], id[u]);
 94         u = fa[t1], t1 = top[u];
 95     }
 96     if(u == v) return ;
 97     if(L[u] < L[v]) swap(u, v);
 98     update(1, 1, tot, id[v], id[u]);
 99 }
100
101 int main()
102 {
103     while(scanf("%d%d%d", &n, &m, &Q) == 3)
104     {
105         for(int i = 1; i <= n; i++) { G[i].clear(); scan(val[i]); }
106         for(int i = 1; i < n; i++)
107         {
108             int u, v; scan(u); scan(v);
109             G[u].push_back(v); G[v].push_back(u);
110         }
111
112         L[1] = fa[1] = 0;
113         dfs(1);
114         tot = 0;
115         dfs2(1, 1);
116
117         memset(add, 0, sizeof(add));
118         char op[10];
119         while(Q--)
120         {
121             int x, y;
122             scanf("%s", op);
123             if(op[0] == ‘Q‘)
124             {
125                 scan(x);
126                 printf("%d\n", val[x] + query(1, 1, tot, x));
127             }
128             else
129             {
130                 scan(x); scan(y); scan(vv);
131                 if(op[0] == ‘D‘) vv = -vv;
132                 Update(x, y);
133             }
134         }
135     }
136
137     return 0;
138 }

代码君

HDU 3966 RE 树链剖分 Aragorn's Story

时间: 2024-08-01 02:19:10

HDU 3966 RE 树链剖分 Aragorn's Story的相关文章

HDU 3966(树链剖分+点修改+点查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题目大意:营地的分布成树型.每个营地都有一些人,每次修改修改一条链上的所有营地的人数,每次查询单个点. 解题思路: 树链剖分基础题. 维护一个sum. 注意轻链修改时,点修改和边修改的不同. 由于树的结构与线段树点的顺序不太相同,因此需要做一个映射数组rank.故在线段树Build的时候,权值是camp[rank[l]],rank这步的映射在dfs2的时候完成,rank[w[u]]=u; Qu

HDU 3966 基础树链剖分

题意:给一棵树,并给定各个点权的值,然后有3种操作:I C1 C2 K: 把C1与C2的路径上的所有点权值加上KD C1 C2 K:把C1与C2的路径上的所有点权值减去KQ C:查询节点编号为C的权值 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #in

hdu 5458 Stability(树链剖分+并查集)

Stability Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 1347    Accepted Submission(s): 319 Problem Description Given an undirected connected graph G with n nodes and m edges, with possibly r

HDU 5044 (树链剖分+树状数组+点/边改查)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变态树链剖分模板题.将以往树链剖分的点&边修改和查询合在一起之后,难度上去不少. 第一个卡人点是读入优化. 第二个卡人点是树状数组.由于要查询所有点,如果使用线段树,每次都要扫到底层才能取出点值,必T无疑. 然后使用树状数组之后,树链剖分的点/边修改写法有些变动. 点查询变化不大. 边查询只要查询一下

HDU 5458 Stability (树链剖分+并查集+set)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条. 这题要倒着做才容易,倒着加边. 因为这题最后保证所有的点一定连通,所以可以构建一棵树,树链剖分一下.要是u到v之间只有一条边,那便是一条割边.而加边的话,就是将u到v之间的边权都+1,边权等于1的话是桥,大于1的话就不是了.所以我们初始化树的时候,可以将边权初始化为1,加边操作将边权赋值为0.求u到v的割边个数的

HDU 5044 Tree 树链剖分

一棵树,初始边权和点权都为0 现在有m个操作,每一个操作: ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k. ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k. 操作完后,输出每一个点的点权和每一条边的边权(边权按照输入顺序输出) 我们把边权也当做点权处

HDU 5242 利用树链剖分思想进行贪心

题目大意: 在给定带权值节点的树上从1开始不回头走到某个底端点后得到所有经过的点的权值后,这些点权值修改为0,到达底部后重新回到1,继续走,问走k次,最多能得到多少权值之和 这其实就是相当于每一次都走权值最大的那一条路径,进行贪心k次 首先先来想想树链剖分的时候的思想: 重儿子表示这个儿子对应的子树的节点数最多,那么每次访问都优先访问重儿子 这道题里面我们进行一下转化,如果当前儿子能走出一条最长的路径,我们就令其为重儿子,那么很容易想到,到达父亲时,如果选择重儿子,那么之前到达 父亲所得的权值一

Hdu 3966 Aragorn&#39;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

HDU 3966 Aragorn&#39;s Story(树链剖分 模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, th