传送门
点分树板题。。。
然而并没有遇到卡常之类的事。。。
对于分出来的每一层用两棵
B
i
t
Bit
Bit动态维护到自己距离不超过
k
k
k的与到自己点分树父亲距离不超过
k
k
k的点数。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=1e5+5;
vector<int>e[N];
int n,m,a[N];
struct Bit{
int up;
vector<int>bit;
inline int lowbit(const int&x){return x&-x;}
inline void init(const int&k){bit.resize(k+10),up=k+8;}
inline void update(int x,const int&v){++x;for(ri i=x;i<=up;i+=lowbit(i))bit[i]+=v;}
inline int query(int x){int ret=0;++x;for(ri i=min(x,up);i>0;i^=lowbit(i))ret+=bit[i];return ret;}
}t1[N],t2[N];
int siz[N],hson[N],top[N],fa[N],dep[N],all,ms,rt,Fa[N];
bool vis[N];
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p])continue;
fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp;
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=fa[p]&&v!=hson[p])dfs2(v,v);
}
inline int lca(int x,int y){
int ret=dep[x]+dep[y];
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return ret-2*dep[dep[x]<dep[y]?x:y];
}
void getroot(int p,int fa){
siz[p]=1;
int mss=0;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa||vis[v])continue;
getroot(v,p),siz[p]+=siz[v],mss=max(mss,siz[v]);
}
mss=max(mss,all-siz[p]);
if(mss<ms)ms=mss,rt=p;
}
int mdp=0,mdpp=0;
void dfs(int p,int fa,int dist,int anc){
siz[p]=1,mdp=max(mdp,dist);
if(anc)mdpp=max(mdpp,lca(anc,p));
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i]]||v==fa)continue;
dfs(v,p,dist+1,anc),siz[p]+=siz[v];
}
}
inline void solve(int p){
vis[p]=1,mdp=1,mdpp=1,dfs(p,0,0,Fa[p]);
t1[p].init(mdp);
if(Fa[p])t2[p].init(mdpp);
for(ri i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i]])continue;
all=ms=siz[v],getroot(v,0),Fa[rt]=p,solve(rt);
}
}
inline int query(int x,int k){
int ret=0;
for(ri t,i=x;i;i=Fa[i]){
if((t=lca(x,i))>k)continue;
ret+=t1[i].query(k-t);
}
for(ri t,i=x;Fa[i];i=Fa[i]){
if((t=lca(x,Fa[i]))>k)continue;
ret-=t2[i].query(k-t);
}
return ret;
}
inline void update(int x,int v){
for(ri i=x;i;i=Fa[i]){
t1[i].update(lca(x,i),v-a[x]);
if(Fa[i])t2[i].update(lca(x,Fa[i]),v-a[x]);
}
a[x]=v;
}
int main(){
n=read(),m=read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs1(1),dfs2(1,1);
all=ms=n,getroot(1,0),solve(rt);
for(ri i=1;i<=n;++i){
for(ri j=i;j;j=Fa[j]){
t1[j].update(lca(i,j),a[i]);
if(Fa[j])t2[j].update(lca(i,Fa[j]),a[i]);
}
}
for(ri ans=0,op,x,y;m;--m){
op=read(),x=read()^ans,y=read()^ans;
switch(op){
case 0:{
cout<<(ans=query(x,y))<<'\n';
break;
}
case 1:{
update(x,y);
break;
}
}
}
return 0;
}