HDU 3966 Aragorn's Story
题意:
给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
思路:
先树链剖分,然后用线段树维护一下
模板题,具体细节看代码
1 const int maxn = 50000 + 10; 2 const int maxnode = maxn * 4; 3 4 int n, m, p; 5 //线段树部分 6 int add_value, qL, qR; 7 int addv[maxnode]; 8 void update(int o, int L, int R) 9 { 10 if (qL <= L && R <= qR) 11 { 12 addv[o] += add_value; 13 } 14 else 15 { 16 int M = L + (R - L) / 2; 17 if (qL <= M) update(lson); 18 if (qR > M) update(rson); 19 } 20 } 21 22 void query(int o, int L, int R, LL add) { 23 if (qL <= L && R <= qR) { 24 printf("%d\n", add + addv[o]); 25 return; 26 } 27 int M = L + (R - L) / 2; 28 if (qL <= M) query(lson, add + addv[o]); 29 if (qR > M) query(rson, add + addv[o]); 30 } 31 32 //树链剖分部分: 33 // 34 //u为连接的点,w为边权 35 struct Edge { int v, w; }; 36 vector<Edge> G[maxn]; 37 38 //往往是双向边 39 void add_edge(int u, int v, int w) 40 { 41 G[u].push_back((Edge){v,w}); 42 G[v].push_back((Edge){u,w}); 43 } 44 45 struct Node 46 { 47 int size, dep, son, top, fa, ti; 48 //依次表示第i个节点的: 49 //子节点数量,深度,所在链的顶端,重儿子,dfs序 50 } t[maxn]; 51 52 int dfs_clock;//DFS时间序列 53 54 void dfs1(int u, int pa, int depth)//第一次DFS,得到size,dep,fa以及son的数据 55 { 56 t[u].son = 0; //重儿子,为0表示没有重儿子 57 t[u].size = 1; //节点数量 58 t[u].dep = depth; 59 t[u].fa = pa; 60 for (int i = 0; i != G[u].size(); ++ i) 61 { 62 int v = G[u][i].v; 63 if (v == pa) continue; 64 dfs1(v, u, depth + 1); 65 t[u].size += t[v].size; 66 if (t[v].size > t[t[u].son].size) t[u].son = v; 67 } 68 } 69 70 void dfs2(int u, int pa) // 得到时间戳等数据,u为当前节点,pa为父链顶端节点 71 { 72 t[u].ti = ++ dfs_clock; //u这个节点的时间戳是dfs_clock,dfs_clock下标是从1开始的,没有0! 73 t[u].top = pa; //top是u所在链的顶端 74 if (t[u].son != 0) dfs2(t[u].son, t[u].top); //如果节点有重儿子,那么依旧是以pa为链顶端的一条链 75 for (int i = 0; i != G[u].size(); ++ i) 76 { 77 int v = G[u][i].v; 78 if (v == t[u].son || v == t[u].fa) continue;//重儿子或者父节点,则跳过 79 dfs2(v, v);//新的一条链 80 } 81 } 82 83 void lca(int x, int y)//更新x到y的之间所有的区间 84 { 85 while (t[x].top != t[y].top) 86 { 87 if (t[t[x].top].dep < t[t[y].top].dep) swap(x,y); //x深 y浅 88 qL=t[t[x].top].ti; 89 qR=t[x].ti; 90 update(1,1,n); 91 x = t[t[x].top].fa; 92 } 93 if (t[x].dep > t[y].dep) swap(x, y);//x是上面一些的节点 94 qL=t[x].ti; 95 qR=t[y].ti; 96 update(1,1,n); 97 } 98 99 int value[maxn]; 100 void init() 101 { 102 dfs_clock = 0; 103 memset(addv, 0, sizeof(addv)); 104 for (int i = 1; i <= n; i++) 105 { 106 scanf("%d", value + i); 107 G[i].clear(); 108 } 109 int u, v; 110 for (int i = 1; i <= m; i++) 111 { 112 scanf("%d%d", &u, &v); 113 add_edge(u, v, 0); 114 } 115 } 116 117 void solve() 118 { 119 dfs1(1, 0, 1); 120 dfs2(1, 0); 121 122 for (int i = 1; i <= n; i++) 123 { 124 add_value = value[i]; 125 qL = qR = t[i].ti; 126 update(1, 1, n); 127 } 128 char op[5]; 129 int u, v, w; 130 while (p--) 131 { 132 scanf("%s", op); 133 if (op[0] == 'Q') 134 { 135 scanf("%d", &u); 136 qL = qR = t[u].ti; 137 query(1, 1, n, 0); 138 continue; 139 } 140 scanf("%d%d%d", &u, &v, &w); 141 if (op[0] == 'D') w = -w; 142 add_value = w; 143 lca(u, v); 144 } 145 } 146 147 int main() 148 { 149 while (scanf("%d%d%d", &n, &m, &p) == 3) 150 { 151 init(); 152 solve(); 153 } 154 return 0; 155 }