Problem Description
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
Input
输入数据第一行是一个整数T(T≤10),表示有T组测试数据。
对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。
接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。
接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。
接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
`#pragma comment(linker, "/STACK:1024000000,1024000000") `
对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。
接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。
接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。
接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
`#pragma comment(linker, "/STACK:1024000000,1024000000") `
Output
对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
Sample Input
1 6 5 0 1 1 2 0 3 3 4 5 3 7 -5 100 20 -5 -7 1 1 1 3 0 2 -1 1 1 1 5
Sample Output
Case #1: 102 27 220
dfs序+线段树
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<map> #include<set> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<bitset> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; typedef __int64 LL; const int low(int x) { return x&-x; } const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int maxn = 2e5 + 10; int T, n, m, x, y, z, cas = 0; int ft[maxn], nt[maxn], u[maxn], sz; int L[maxn], R[maxn], tot; LL f[maxn << 1], vv[maxn], v[maxn], sum[maxn << 1]; void dfs(int x, int fa, LL value) { L[x] = ++tot; vv[tot] = value; for (int i = ft[x]; i != -1; i = nt[i]) { if (u[i] == fa) continue; dfs(u[i], x, value + v[u[i]]); } R[x] = tot; } void build(int x, int l, int r) { sum[x] = 0; if (l == r) { f[x] = vv[l]; return; } int mid = l + r >> 1; build(x << 1, l, mid); build(x << 1 | 1, mid + 1, r); f[x] = max(f[x << 1], f[x << 1 | 1]); } void pushdown(int x) { sum[x << 1] += sum[x]; sum[x << 1 | 1] += sum[x]; f[x << 1] += sum[x]; f[x << 1 | 1] += sum[x]; sum[x] = 0; } LL get(int x, int l, int r, int ll, int rr) { if (l < r&&sum[x]) pushdown(x); if (ll <= l&&r <= rr) return f[x]; int mid = l + r >> 1; if (rr <= mid) return get(x << 1, l, mid, ll, rr); if (mid < ll) return get(x << 1 | 1, mid + 1, r, ll, rr); return max(get(x << 1, l, mid, ll, rr), get(x << 1 | 1, mid + 1, r, ll, rr)); f[x] = max(f[x << 1], f[x << 1 | 1]); } void change(int x, int l, int r, int ll, int rr, LL v) { if (l < r&&sum[x]) pushdown(x); if (ll <= l&&r <= rr) { f[x] += v, sum[x] += v; return; } int mid = l + r >> 1; if (ll <= mid) change(x << 1, l, mid, ll, rr, v); if (mid < rr) change(x << 1 | 1, mid + 1, r, ll, rr, v); f[x] = max(f[x << 1], f[x << 1 | 1]); } int main() { scanf("%d", &T); while (T--) { tot =- 1; sz = 0; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) ft[i] = -1; for (int i = 1; i < n; i++) { scanf("%d%d", &x, &y); u[sz] = y; nt[sz] = ft[x]; ft[x] = sz++; u[sz] = x; nt[sz] = ft[y]; ft[y] = sz++; } for (int i = 0; i < n; i++) scanf("%I64d", &v[i]); dfs(0, -1, v[0]); build(1, 0, n - 1); printf("Case #%d:\n", ++cas); while (m--) { scanf("%d", &x); if (x == 0) { scanf("%d%d", &y, &z); change(1, 0, n - 1, L[y], R[y], z - v[y]); v[y] = z; } else { scanf("%d", &y); printf("%I64d\n", get(1, 0, n - 1, L[y], R[y])); } } } return 0; }