5692 Snacks (線段樹+ dfs)
阿新 • • 發佈:2018-12-10
題意:
一棵樹0為頂點,n個頂點 (n-1)條邊,問如果必須經過一個點,權值最大的一條路的權值是多少
思路:
因為n個點,(n-1)條邊,所以從頂點每個點只有一條路,可以用dfs求出從頂點到每一個點的距離,而且題目中有修改點的值的要求,所以可以想到線段樹,而用dfs的話,會發現一個父節點的所有子節點遍歷完後才會遍歷到這個父節點。 所以如果在dfs途中,對每個點重新編號的話,父節點所有的子節點可以組成一個連續的區間,[L,R],L是指所有子節點的最小值,R是父節點本身(因為父節點一定比它的所有子節點大),而求經過這個父節點的最大權值,就是它的區間的最大值,而區間的最值可用線段樹解決 那樣例舉個例子:
AC程式碼
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define LL long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 200005
#define eps 0.00000001
#define PI acos(-1.0)
#define M 1000000007
struct Edge{
int v, nxt;
}edge[maxn << 2];
struct Tree{
int l, r;
LL w, lazy;
}tree[maxn << 2];
int head[maxn], tot, L[maxn], R[maxn], Index, Ll, Rr;
LL num[maxn], w[maxn], ans, ww;
void init() {
Index = tot = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot ++;
edge[tot].v = u;
edge[tot].nxt = head[v];
head[v] = tot ++;
}
void Built(int k, int ll, int rr) {
tree[k].l = ll; tree[k].r = rr;
tree[k].lazy = 0;
if(ll == rr) {
tree[k].w = num[ll];
return ;
}
int mm = (ll + rr) >> 1;
Built(k << 1, ll, mm);
Built(k << 1|1, mm + 1, rr);
tree[k].w = max(tree[k << 1].w, tree[k << 1|1].w);
}
void Down(int k) {
tree[k << 1].lazy += tree[k].lazy;
tree[k << 1|1].lazy += tree[k].lazy;
tree[k << 1].w += tree[k].lazy;
tree[k << 1|1].w += tree[k].lazy;
tree[k].lazy = 0;
}
void change_Interval(int k) {
if(tree[k].l >= Ll && tree[k].r <= Rr) {
tree[k].w += ww;
tree[k].lazy += ww;
return;
}
if(tree[k].lazy != 0) Down(k);
int mm = (tree[k].l + tree[k].r) >> 1;
if(mm >= Ll) change_Interval(k << 1);
if(mm < Rr) change_Interval(k << 1|1);
tree[k].w = max(tree[k << 1].w, tree[k << 1|1].w);
}
void ask_Interval(int k) {
if(tree[k].l >= Ll && tree[k].r <= Rr) {
ans = max(ans, tree[k].w);
return;
}
if(tree[k].lazy != 0) Down(k);
int mm = (tree[k].l + tree[k].r) >> 1;
if(mm >= Ll) ask_Interval(k << 1);
if(mm < Rr) ask_Interval(k << 1|1);
}
void dfs(int u, int parent, LL sum) {
sum += w[u]; L[u] = INF;
for (int i = head[u]; i + 1; i = edge[i].nxt) {
int son = edge[i].v;
if(son == parent) continue;
dfs(son, u, sum);
L[u] = min(L[u], L[son]);
}
R[u] = ++Index;
num[Index] = sum;
if(L[u] == INF) L[u] = R[u];
}
int main(int argc, const char * argv[]) {
int T;
scanf("%d", &T);
for (int Case = 1; Case <= T; Case ++) {
printf("Case #%d:\n", Case);
init();
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i < n; i ++) {
int u, v;
scanf("%d %d", &u, &v);
addEdge(u, v);
}
for (int i = 0; i < n; i ++)
scanf("%lld", &w[i]);
dfs(0, 0, 0);
Built(1, 1, n);
for (int i = 0; i < m; i ++) {
int flag;
scanf("%d", &flag);
if(!flag) {
int wh, y;
scanf("%d %d", &wh, &y);
ww = y - w[wh];
Ll = L[wh]; Rr = R[wh];
w[wh] = y;
change_Interval(1);
}else {
int wh;
scanf("%d", &wh);
ans = -9999999999999999; Ll = L[wh]; Rr = R[wh];
ask_Interval(1);
printf("%lld\n", ans);
}
}
}
return 0;
}