题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:给出一棵树,有三种操作:
1.(u, v)路径上的点权值全部加上X
2.(u, v)路径上的点权值全部减去X
3.查询u点的值
思路:树链剖分,然后区间更新,单点查询
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int maxn = 100010; struct Edge { int to, next; } edge[maxn << 1]; int head[maxn], tot, val[maxn]; int top[maxn], fa[maxn], deep[maxn]; int num[maxn], p[maxn], fp[maxn]; int son[maxn], pos, mp[maxn]; void init() { tot = 0; memset(head, -1, sizeof(head)); pos = 1; memset(son, -1, sizeof(son)); } void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs1(int u, int pre, int d) { deep[u] = d; fa[u] = pre; num[u] = 1; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != pre) { dfs1(v, u, d + 1); num[u] += num[v]; if (son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } } void getpos(int u, int sp) { top[u] = sp; mp[u] = p[u] = pos++; fp[p[u]] = u; if (son[u] == -1) return; getpos(son[u], sp); mp[u] = max(mp[u], mp[son[u]]); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != son[u] && v != fa[u]) getpos(v, v); mp[u] = max(mp[u], mp[v]); } } int sum[maxn << 2], col[maxn << 2]; void pushup(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void pushdown(int rt, int m) { if (col[rt]) { col[rt << 1] += col[rt]; col[rt << 1 | 1] += col[rt]; sum[rt << 1] += (m - (m >> 1)) * col[rt]; sum[rt << 1 | 1] += (m >> 1) * col[rt]; col[rt] = 0; } } void build(int l, int r, int rt) { col[rt] = 0; if (l == r) { sum[rt] = val[fp[l]]; return ; } int mid = (l + r) >> 1; build(lson); build(rson); pushup(rt); } void update(int ql, int qr, int c, int l, int r, int rt) { if (ql <= l && r <= qr) { col[rt] += c; sum[rt] += (r - l + 1) * c; return ; } pushdown(rt, r - l + 1); int mid = (l + r) >> 1; if (ql <= mid) update(ql, qr, c, lson); if (qr > mid) update(ql, qr, c, rson); pushup(rt); } int query(int k, int l, int r, int rt) { if (l == r) return sum[rt]; pushdown(rt, r - l + 1); int res = 0; int mid = (l + r) >> 1; if (k <= mid) res += query(k, lson); else res += query(k, rson); return res; } void change(int u, int v, int c) { int fu = top[u], fv = top[v]; while (fu != fv) { if (deep[fu] < deep[fv]) { swap(fu, fv); swap(u, v); } update(p[fu], p[u], c, 1, pos, 1); u = fa[fu], fu = top[u]; } if (deep[u] > deep[v]) swap(u, v); update(p[u], p[v], c, 1, pos, 1); } int main() { int n, m, q; while (~scanf("%d%d%d", &n, &m, &q)) { init(); for (int i = 1; i <= n; i++) scanf("%d", &val[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } dfs1(1, 0, 0); getpos(1, 1); build(1, pos, 1); while (q--) { char op[10]; int x, y, z; scanf("%s", op); if (op[0] == 'I') { scanf("%d%d%d", &x, &y, &z); change(x, y, z); } else if (op[0] == 'D') { scanf("%d%d%d", &x, &y, &z); change(x, y, -z); } else { scanf("%d", &x); printf("%d\n", query(p[x], 1, pos, 1)); } } } return 0; }