#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10000;
typedef long long ll;
int op;
int n,q,m;
int e[N<<1],ne[N<<1],h[N<<1],idx,cnt;
int a[N];
int rk[N],son[N],dep[N],fa[N],top[N],size[N],id[N];
struct node
{
int l,r,mx,size;
ll w;
}tr[N<<1];
void add(int u,int v)
{
e[idx]=v;ne[idx]=h[u];h[u]=idx++;
}
void dfs1(int u,int father,int depth)
{
dep[u]=depth;fa[u]=father;size[u]=1;
for(int i=h[u];~i;i=ne[i])
{
int v=e[i];
if(v==father) continue;
dfs1(v,u,depth+1);
size[u]+=size[v];
if(size[v]>size[son[u]])
{
son[u]=v;
}
}
}
void dfs2(int u,int v)
{
top[u]=v;
id[u]=++cnt;
rk[cnt]=a[u];
if(!son[u]) return ;
dfs2(son[u],v);
for(int i=h[u];~i;i=ne[i])
{
int v=e[i];
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
int Inmax(int u,int l,int r)
{
int ans=-1e9;
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].mx;
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) ans=max(ans,Inmax(u<<1,l,r));
if(r>mid) ans=max(ans,Inmax(u<<1|1,l,r));
return ans;
}
int Intermax(int x,int y)
{
int ans=-1e9;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
// cout<<id[top[x]]<<" "<<id[x]<<endl;
ans=max(ans,Inmax(1,id[top[x]],id[x]));
x=fa[top[x]];
// cout<<x<<endl;
// cout<<ans<<endl;
}
if(dep[x]>dep[y]) swap(x,y);
ans=max(ans,Inmax(1,id[x],id[y]));
return ans;
}
void push_up(int u)
{
tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx) ;
tr[u].w=(tr[u<<1].w+tr[u<<1|1].w);
}
void build(int u,int l,int r)
{
tr[u].l=l;tr[u].r=r;
if(l==r){
tr[u].mx=rk[l];
tr[u].w=rk[l];
return ;
}
int mid=l+r>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
push_up(u);
}
ll Insum(int u,int l,int r)
{
ll ans=0;
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].w;
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) ans=(ans+Insum(u<<1,l,r));
if(r>mid) ans=(ans+Insum(u<<1|1,l,r));
return ans;
}
ll querysum(int x,int y)
{
ll ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=(ans+Insum(1,id[top[x]],id[x]));
//cout<<ans<<endl;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
// cout<<id[x]<<" "<<id[y]<<endl;
ans=(ans+Insum(1,id[x],id[y]));
//cout<<ans<<endl;
return ans;
}
void update(int u,int x,int val)
{
if(tr[u].l==tr[u].r)
{
tr[u].w=tr[u].mx=val;
return ;
}
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) update(u<<1,x,val);
if(x>mid) update(u<<1|1,x,val);
push_up(u);
}
void init()
{
memset(dep,0,sizeof dep);
memset(size,0,sizeof size);
memset(tr,0,sizeof tr);
memset(son,0,sizeof son);
memset(fa,0,sizeof fa);
memset(top,0,sizeof top);
memset(rk,0,sizeof rk);
memset(id,0,sizeof id);
memset(e,0,sizeof e);
memset(ne,0,sizeof ne);
idx=0;
cnt=0;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(h,-1,sizeof h);
init();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1,x,y;i<=n-1;i++)
{
scanf("%d %d",&x,&y);
add(x,y);add(y,x);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d",&op);
if(op==0)
{
scanf("%d %d",&u,&v);
printf("%d\n",Intermax(u,v) );
}
else if(op==1)
{
scanf("%d %d",&u,&v);
printf("%lld\n",querysum(u,v));
}
else if(op==2)
{
scanf("%d %d",&u,&v);
update(1,id[u],v);
}
}
}
}
不存在的树------------------------思维(树链剖分)
最新推荐文章于 2024-05-21 20:44:10 发布