题目链接:点我~~
先dfs求出欧拉序列,就是dfs遍历的顺序,然后更新是更新区间加一个数,查询是查询区间的最大值,即l[x]到r[x]间的最大值,l[x]表示第一次遍历到x点,r[x]表示遍历完有关x节点时的值,区间内就表示有关x的所有值~
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<fstream>
using namespace std;
typedef long long LL;
const LL INF = 1e18 + 7;
const int N = 200100;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
vector<int> mp[N];
int cnt[N];
int val[N];
int l[N], r[N];
int tol;
LL msum[N << 2], sval[N], col[N << 2];
void dfs(int u, int fa)
{
cnt[++tol] = u;
l[u] = tol;
for (int i = 0; i < mp[u].size(); ++i)
{
int v = mp[u][i];
if (v == fa)
{
continue;
}
sval[v] += sval[u];
dfs(v, u);
}
r[u] = tol;
}
inline void pushup(int rt)
{
msum[rt] = max(msum[rt << 1], msum[rt << 1 | 1]);
}
void pushdown(int rt)
{
if (col[rt])
{
col[rt << 1] += col[rt];
col[rt << 1 | 1] += col[rt];
msum[rt << 1] += col[rt];
msum[rt << 1 | 1] += col[rt];
col[rt] = 0;
}
}
void build(int l, int r, int rt)
{
msum[rt] = 0;
col[rt] = 0;
if (l == r)
{
msum[rt] = sval[cnt[l]];
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
void modify(int l, int r, int rt, int tl, int tr, int res)
{
if (tl <= l && r <= tr)
{
msum[rt] += res;
col[rt] += res;
return;
}
pushdown(rt);
int m = (l + r) >> 1;
if (tl <= m)
{
modify(lson, tl, tr, res);
}
if (tr > m)
{
modify(rson, tl, tr, res);
}
pushup(rt);
}
LL query(int l, int r, int rt, int tl, int tr)
{
if (tl <= l && r <= tr)
{
return msum[rt];
}
pushdown(rt);
int m = (l + r) >> 1;
LL res= -INF;
if (tl <= m)
{
res=max(res,query(lson, tl, tr));
}
if (tr > m)
{
res=max(res,query(rson, tl, tr));
}
return res;
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int t;
int casee = 1;
cin >> t;
int n, m;
while (t--)
{
cin>>n>>m;
for (int i = 1; i <= n; ++i)
{
mp[i].clear();
}
int u, v;
for (int i = 1; i < n; ++i)
{
scanf("%d%d", &u, &v);
u++, v++;
mp[u].push_back(v);
mp[v].push_back(u);
}
for (int i = 1; i <= n; ++i)
{
scanf("%d", &val[i]);
sval[i] = val[i];
}
tol = 0;
dfs(1, 0);
//cout<<tol<<endl;
build(1, n, 1);
printf("Case #%d:\n", casee++);
int op, x, y;
while (m--)
{
scanf("%d", &op);
if (op == 0)
{
scanf("%d%d", &x, &y);
x++;
modify(1, n, 1, l[x], r[x], y-val[x]);
val[x] = y;
}
else
{
scanf("%d", &x);
x++;
cout << query(1, n, 1, l[x], r[x]) << endl;
}
}
}
return 0;
}
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/986 (转载时请注明本文出处及文章链接)


发表评论
快来吐槽一下吧!