HDU 3966 Aragorn's Story(树链剖分)

来源:互联网 发布:骚气的诗词 知乎 编辑:程序博客网 时间:2024/04/30 22:49

题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K : 把 C1 与 C2 的路径上的所有点权值加上 K
D C1 C2 K:把 C1 与 C2 的路径上的所有点权值减去 K
Q C:查询节点编号为C的权值。

思路:树链剖分.............一开始线段树写sb了wa了一下午.............正好又练习了一下线段树........

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii (pair<int, int>)#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int maxn = 50005;const int INF = 1400000000;int addv[maxn*4], maxv[maxn*4];int W[maxn]; void maintain(int o, int L, int R) {int lc = o*2, rc = o*2+1;maxv[o] = 0;if(R > L) {   //考虑左右子树 maxv[o] = max(maxv[lc], maxv[rc]);}maxv[o] += addv[o];//考虑add操作 } void update(int o, int L, int R, int v, int yl, int yr) {int lc = o*2, rc = o*2+1;if(yl <= L && yr >= R) {   //递归边界 addv[o] += v;//累加边界的add值 } else {int M = L + (R-L)/2;if(yl <= M) update(lc, L, M, v, yl, yr);if(yr > M) update(rc, M+1, R, v, yl, yr);}maintain(o, L, R);//递归结束前重新计算本节点的附加信息 } int query(int o, int L, int R, int add, int yl, int yr) {int ans = -INF;if(yl <= L && yr >= R) {return maxv[o] + add;} else {int M = L + (R-L)/2;if(yl <= M) ans = max(ans, query(o*2, L, M, add + addv[o], yl, yr));if(yr > M) ans = max(ans, query(o*2+1, M+1, R, add + addv[o], yl, yr));}return ans;} int n, gan, q, tot;vector<int> G[maxn];int siz[maxn], son[maxn], dep[maxn], top[maxn], fa[maxn], pos[maxn], arc[maxn];void init() {for(int i = 1; i <= n; i++) G[i].clear();tot = 0;memset(son, 0, sizeof(son));memset(addv, 0, sizeof(addv));memset(maxv, 0, sizeof(maxv));}void dfs(int cur, int f) {siz[cur] = 1;int tmp = 0;for(int i = 0; i < G[cur].size(); i++) {int u = G[cur][i];if(u == f) continue;dep[u] = dep[cur] + 1;fa[u] = cur;dfs(u, cur);siz[cur] += siz[u];if(siz[u] > tmp) son[cur] = u, tmp = siz[u];}}void dfs2(int cur, int tp) {top[cur] = tp;pos[cur] = ++tot;arc[tot] = cur;if(son[cur]) dfs2(son[cur], tp);for(int i = 0; i < G[cur].size(); i++) {int u = G[cur][i];if(u==son[cur] || u==fa[cur]) continue;dfs2(u, u);}}void modify(int u, int v, int d) {int fu = top[u], fv = top[v];while(fu != fv) {if(dep[fu]<dep[fv]) swap(fu, fv), swap(u, v);update(1, 1, n, d, pos[fu], pos[u]);u = fa[fu]; fu = top[u];}if(dep[u]<dep[v]) swap(u, v);update(1, 1, n, d, pos[v], pos[u]);}void Build(int o, int L, int R) {if(L == R) maxv[o]=W[arc[L]], addv[o]+=maxv[o];else {int M = L + (R-L)/2;Build(2*o, L, M); Build(2*o+1, M+1, R);maxv[o] = max(maxv[2*o], maxv[2*o+1]);}}int main() {    //freopen("input.txt", "r", stdin);while(scanf("%d%d%d", &n, &gan, &q)==3) {init();for(int i = 1; i <= n; i++) scanf("%d", &W[i]);for(int i = 1; i <= n-1; i++) {int u, v; scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}dfs(1, 0);dfs2(1, 1);Build(1, 1, n);char op[10];while(q--) {scanf("%s", op);int u, v, d;if(op[0] == 'Q') {scanf("%d", &u);printf("%d\n", query(1, 1, n, 0, pos[u], pos[u]));}else if(op[0] == 'D'){scanf("%d%d%d", &u, &v, &d);modify(u, v, -d);}else {scanf("%d%d%d", &u, &v, &d);modify(u, v, d);}}}    return 0;}


0 0
原创粉丝点击