傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=5692
兩場百度之星打的十分鬱悶,但是也發現了我還是有很多的知識不能靈活運用,比如這題,dfs序我是懂的,線段樹也是懂的,但是就是不知道怎麼來做這題。
賽後看了takio菊苣的代碼,覺得代碼風格非常的清晰,很多地方加了空格以後看起來確實清楚很多。準備學習一下,雖然很影響手速,但是也慢慢改一改吧。
這題的思路實際上是這樣的。先通過一次dfs來求得很多信息,比如dfs序,距離0點的距離,線段樹中的下標代表的點。然後把距離0點的距離做成一棵線段樹,這樣的話,在x的子樹的序列中,[L[x], R[x]]這段區間內,一定有0點到某個最遠的點的距離,如果求出這個區間內的最大值,那麼就是題目要求的最大距離。我們考慮修改操作,如果修改一個點的值的話,其實就是相當於修改整個子樹的值,那麼就用一個區間修改操作直接修改整個區間的值就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define ls l, m
#define rs m + 1, r
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define calm (l + r) >> 1
const ll INF = 1e15;
const int maxn = 100010;
struct EE {
int to, next;
EE(){}
EE(int to, int next):to(to), next(next){}
}edge[maxn << 1];
struct node {
ll mx, tag;
}tree[maxn << 2];
int n, m, Case, Ecnt, tot;
int head[maxn], L[maxn], R[maxn], rev[maxn];
ll a[maxn], val[maxn];
inline void add (int from, int to) {
edge[Ecnt] = EE(to, head[from]);
head[from] = Ecnt++;
}
void dfs (int s, int pre) {
val[s] += val[pre]; L[s] = ++tot; rev[tot] = s;
for (int i = head[s]; ~i; i = edge[i].next) {
int t = edge[i].to;
if (t == pre) continue;
dfs (t, s);
}
R[s] = tot;
}
inline void pushup (int rt) {
tree[rt].mx = max (tree[rt << 1].mx, tree[rt << 1 | 1].mx);
}
inline void pushdown (int rt) {
if (tree[rt].tag) {
tree[rt << 1].mx += tree[rt].tag;
tree[rt << 1 | 1].mx += tree[rt].tag;
tree[rt << 1].tag += tree[rt].tag;
tree[rt << 1 | 1].tag += tree[rt].tag;
tree[rt].tag = 0;
}
}
void build (int l, int r, int rt) {
tree[rt].tag = 0;
if (l == r) {
tree[rt].mx = val[rev[l]];
return;
}
int m = calm;
build (lson); build (rson);
pushup (rt);
}
void update (int L, int R, int c, int l, int r, int rt) {
if (L <= l && r <= R) {
tree[rt].mx += c;
tree[rt].tag += c;
return;
}
pushdown (rt);
int m = calm;
if (L <= m) update (L, R, c, lson);
if (R > m) update (L, R, c, rson);
pushup (rt);
}
ll query (int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return tree[rt].mx;
}
pushdown (rt);
int m = calm;
ll ans = -INF;//INF要設的大一點
if (L <= m) ans = query (L, R, lson);
if (R > m) ans = max (ans, query (L, R, rson));
return ans;
}
int main() {
// freopen ("D://input.txt", "r", stdin);
int T; scanf ("%d", &T);
while (T--) {
printf ("Case #%d:\n", ++Case);
scanf ("%d%d", &n, &m);
memset (head, -1, sizeof head); Ecnt = 0;
for (int i = 1; i < n; i++) {
int x, y; scanf ("%d%d", &x, &y);
++x; ++y;
add (x, y); add (y, x);
}
for (int i = 1; i <= n; i++) {
scanf ("%I64d", &a[i]);
val[i] = a[i];
}
tot = 0; dfs (1, 0);
build (1, n, 1);
while (m--) {
int op, x; scanf ("%d%d", &op, &x); ++x;
if(!op) {
int y; scanf ("%d", &y);
update (L[x], R[x], y - a[x], 1, n, 1);
a[x] = y;
}
else {
printf ("%I64d\n", query (L[x], R[x], 1, n, 1));
}
}
}
return 0;
}