题目链接
参考
Code
#include <bits/stdc++.h>
using namespace std;
#define RG register int
#define LL long long
template<typename elemType>
inline void Read(elemType &T){
elemType X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
T=(w?-X:X);
}
const int maxn=100010;
const int INF=1<<30;
struct Graph{
struct edge{int Next,to;};
edge G[maxn<<1];
int head[maxn],cnt;
Graph():cnt(2){}
void clear(int n){cnt=2;fill(head,head+n+2,0);}
void add_edge(int u,int v){
G[cnt].to=v;
G[cnt].Next=head[u];
head[u]=cnt++;
}
};
template<size_t n>
struct HLD{
int fa[n],top[n],hson[n],sz[n],deep[n];
Graph &G;int root;
HLD(Graph &_G):G(_G){}
void DFS_Init(int u){
sz[u]=1;deep[u]=deep[fa[u]]+1;
for(int i=G.head[u];i;i=G.G[i].Next){
int v=G.G[i].to;
if(v==fa[u]) continue;
fa[v]=u;
DFS_Init(v);
sz[u]+=sz[v];
if(sz[hson[u]]<sz[v]) hson[u]=v;
}
}
void DFS(int u,int anc){
top[u]=anc;
if(!hson[u]) return;
DFS(hson[u],anc);
for(int i=G.head[u];i;i=G.G[i].Next){
int v=G.G[i].to;
if(v==fa[u] || v==hson[u]) continue;
DFS(v,v);
}
}
void build(int _root){
root=_root;
fa[root]=0;DFS_Init(root);DFS(root,root);
}
int LCA(int u,int v){
while(top[u]!=top[v]){
if(deep[top[u]]<deep[top[v]]) swap(u,v);
u=fa[top[u]];
}
if(deep[u]>deep[v]) swap(u,v);
return u;
}
int getDis(int u,int v){return deep[u]+deep[v]-(deep[LCA(u,v)]<<1);}
};
template<typename elemType>
struct BIT{
inline int lowbit(int x){return x&(-x);}
int n;vector<elemType> Node;
void build(int _n){n=_n;Node.resize(n+1);}
void Update(int x,elemType Add){
++x;for(;x<=n;x+=lowbit(x)) Node[x]+=Add;
}
elemType PrefixSum(elemType x){
++x;x=min(x,n);elemType Res=0;
for(;x;x-=lowbit(x))
Res+=Node[x];return Res;
}
elemType Query(int L,int R){return PrefixSum(R)-PrefixSum(L-1);}
};
Graph G;
HLD<maxn> hld(G);
BIT<int> TR1[maxn],TR2[maxn];
int Value[maxn],Size[maxn],Fa[maxn];
bool vis[maxn];
int N,M,Root,CurSize,MaxSize;
void GetRoot(int u,int fa){
Size[u]=1;
int mx=0;
for(int i=G.head[u];i;i=G.G[i].Next){
int v=G.G[i].to;
if(vis[v] || v==fa) continue;
GetRoot(v,u);
Size[u]+=Size[v];
mx=max(mx,Size[v]);
}
mx=max(mx,CurSize-Size[u]);
if(mx<MaxSize){MaxSize=mx;Root=u;}
}
void Divide(int u,int fa){
vis[u]=true;Fa[u]=fa;
TR1[u].build((CurSize>>1)+1);
TR2[u].build(CurSize+1);
for(int i=G.head[u];i;i=G.G[i].Next){
int v=G.G[i].to;
if(vis[v]) continue;
CurSize=MaxSize=Size[v];
Root=0;GetRoot(v,0);
Divide(Root,u);
}
}
void Change(int u,int v){
TR1[u].Update(0,v);
for(int x=u;Fa[x];x=Fa[x]){
int d=hld.getDis(u,Fa[x]);
TR1[Fa[x]].Update(d,v);
TR2[x].Update(d,v);
}
}
int Ask(int u,int K){
int ans=TR1[u].PrefixSum(K);
for(int x=u;Fa[x];x=Fa[x]){
int d=hld.getDis(u,Fa[x]);
if(d>K) continue;
ans+=TR1[Fa[x]].PrefixSum(K-d);
ans-=TR2[x].PrefixSum(K-d);
}
return ans;
}
int main(){
Read(N);Read(M);
for(int i=1;i<=N;++i)
Read(Value[i]);
for(int i=1;i<=N-1;++i){
int u,v;Read(u);Read(v);
G.add_edge(u,v);
G.add_edge(v,u);
}
hld.build(1);CurSize=N;
CurSize=MaxSize=N;Root=0;GetRoot(1,0);
Divide(Root,0);
for(int i=1;i<=N;++i)
Change(i,Value[i]);
int lastans=0;
while(M--){
int opt,u,v;
Read(opt);Read(u);Read(v);
u^=lastans;v^=lastans;
if(opt){Change(u,v-Value[u]);Value[u]=v;}
else printf("%d\n",lastans=Ask(u,v));
}
return 0;
}