ポータル
タイトル説明
Baidu Science Parkにはn台のスナックマシンがあり、スナックマシンはn-1本の道路で相互に接続されています。各スナックマシンの値はvで、XiaoduBearにスナックを提供する価値を表します。
スナックは頻繁に消費され、補充されるため、スナックマシンの値vは時々変化します。Xiaodu Xiongは、番号0のスナックマシンからのみ開始でき、各スナックマシンは最大で1回通過します。さらに、Xiaodu Xiongは特定のスナックマシンのスナックを優先し、スナックマシンがルート上にある必要があります。
ルートの合計値を最大化するために、XiaoduBearのルートを計画します。
分析
この質問では、ツリー構造をチェーン構造に変換して次のノードから各ノードまでの距離を維持し、次にラインセグメントを使用して間隔の最大値を維持し、ポイントの値を変更できます。実際、このポイントとこの時点でのサブツリーの変更も間隔の変更に変換されるため、dfsを使用してこのツリーをチェーンに変換し、ラインセグメントツリーを使用して間隔のクエリと変更を実行できます。
コード
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const ll INF = 0x3f3f3f3f3f3f;
const int N = 100010;
int h[N],ne[N * 2],e[N * 2],idx;
ll d[N],s[N];
int in[N],out[N];
int n,m;
int cnt;
struct Node{
int l,r;
ll sum,add;
}tr[N << 2];
void add(int x,int y){
ne[idx] = h[x],e[idx] = y,h[x] = idx++;
}
void dfs(int u,int fa,ll pp){
in[u] = ++cnt;
d[cnt] = pp;
for(int i = h[u];~i;i = ne[i]){
int j = e[i];
if(j == fa) continue;
dfs(j,u,pp + s[j]);
}
out[u] = cnt;
}
void pushup(int u){
tr[u].sum = max(tr[u << 1].sum,tr[u << 1 | 1].sum);
}
void down(int u){
auto &f = tr[u],&l = tr[u << 1],&r = tr[u << 1 | 1];
if(f.add){
l.add += f.add,l.sum += f.add;
r.add += f.add,r.sum += f.add;
f.add = 0;
}
}
void build(int u,int l,int r){
tr[u].l = l,tr[u].r = r,tr[u].add = 0;
if(l == r){
tr[u].sum = d[l];
return;
}
int mid = l + r >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
pushup(u);
}
void modify(int u,int l,int r,ll x){
if(tr[u].l >= l && tr[u].r <= r){
tr[u].sum += x;
tr[u].add += x;
return;
}
down(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify(u << 1,l,r,x);
if(r > mid) modify(u << 1 | 1,l,r,x);
pushup(u);
}
ll query(int u,int l,int r){
if(tr[u].l >= l && tr[u].r <= r){
return tr[u].sum;
}
down(u);
int mid = tr[u].l + tr[u].r >> 1;
ll ans = -INF;
if(l <= mid) ans = query(u << 1,l,r);
if(r > mid) ans = max(query(u << 1 | 1,l,r),ans);
return ans;
}
int main(){
int t;
scanf("%d",&t);
for(int ppp = 1;ppp <= t;ppp++){
memset(h,-1,sizeof h);
idx = cnt = 0;
scanf("%d%d",&n,&m);
printf("Case #%d:\n",ppp);
for(int i = 1;i < n;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
for(int i = 0;i < n;i++) scanf("%lld",&s[i]);
dfs(0,-1,s[0]);
build(1,1,n);
while(m--){
int op,x,y;
scanf("%d%d",&op,&x);
if(!op){
scanf("%d",&y);
ll add = 1ll * y - s[x];
modify(1,in[x],out[x],add);
s[x] = y;
}
else printf("%lld\n",query(1,in[x],out[x]));
}
}
}