#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxN 400010
#define ll long long
#define F(i,j,n) for (int i=j; i<=n; i++)
struct Tnode{
int v,nxt;
}edge[maxN];
int dep[maxN],fa[maxN],sz[maxN],start[maxN],end[maxN],top[maxN],son[maxN],a[maxN];
ll tr_max[maxN*4],tr_sum[maxN*4];
int first[maxN],tot,tim;
int n,m;
void init(){ memset(first,-1,sizeof first); memset(son,-1,sizeof son); tot=tim=0;}
void add(int u,int v){ edge[++tot].v=v; edge[tot].nxt=first[u]; first[u]=tot;}
void dfs1(int u,int dad)
{
dep[u]=dep[dad]+1;
fa[u]=dad;
sz[u]=1;
for (int i=first[u]; i!=-1; i=edge[i].nxt)
{
int v=edge[i].v;
if (v!=fa[u])
{
dfs1(v,u);
sz[u]+=sz[v];
if (son[u]==-1 || sz[son[u]]<sz[v]) son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
start[u]=++tim;
top[u]=tp;
if (son[u]!=-1) dfs2(son[u],tp);
for (int i=first[u]; i!=-1; i=edge[i].nxt)
{
int v=edge[i].v;
if (v!=fa[u] && v!=son[u]) dfs2(v,v);
}
end[u]=tim;
}
void update1(int l,int r,int root,int L,int R,int c)
{
if (l>R || L>r || tr_max[root]<c) return ;
if (l==r)
{
tr_max[root]=tr_max[root]%c;
tr_sum[root]=tr_sum[root]%c;
return ;
}
int mid=(l+r)/2;
update1(l,mid,root*2,L,R,c);
update1(mid+1,r,root*2+1,L,R,c);
tr_max[root]=max(tr_max[root*2],tr_max[root*2+1]);
tr_sum[root]=tr_sum[root*2]+tr_sum[root*2+1];
}
void update2(int l,int r,int root,int pos,int c)
{
if (l==r)
{
tr_max[root]=c;
tr_sum[root]=c;
return ;
}
int mid=(l+r)/2;
if (l<=pos && pos<=mid) update2(l,mid,root*2,pos,c);
if (mid+1<=pos && pos<=r) update2(mid+1,r,root*2+1,pos,c);
tr_max[root]=max(tr_max[root*2],tr_max[root*2+1]);
tr_sum[root]=tr_sum[root*2]+tr_sum[root*2+1];
}
ll query(int l,int r,int root,int L,int R)
{
if (l>R || L>r) return 0;
if (L<=l && r<=R) return tr_sum[root];
int mid=(l+r)/2;
return query(l,mid,root*2,L,R)+query(mid+1,r,root*2+1,L,R);
}
ll solve(int u,int v)
{
ll sum=0;
while (top[u]!=top[v])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
sum=sum+query(1,n,1,start[top[u]],start[u]);
//printf("u:%d topu:%d v:%d topv:%d \n",u,top[u],v,top[v]);
// printf("query:%d\n\n",query(1,n,1,start[top[u]],start[u]));
u=fa[top[u]];
}
if (dep[u]<dep[v]) swap(u,v);
sum=sum+query(1,n,1,start[v],start[u]);
return sum;
}
int main()
{
freopen("2103.in","r",stdin);
freopen("2103.out","w",stdout);
scanf("%d%d",&n,&m);
init();
int x,u,v;
F(i,1,n-1)
{
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
F(i,1,n) scanf("%d",&a[i]);
dfs1(1,1);
dfs2(1,1);
F(i,1,n) update2(1,n,1,start[i],a[i]);
F(i,1,m)
{
scanf("%d%d%d",&x,&u,&v);
if (x==1) update1(1,n,1,start[u],end[u],v);
if (x==2) update2(1,n,1,start[u],v);
if (x==3) printf("%lld\n",solve(u,v));
}
return 0;
}
树链剖分
最新推荐文章于 2024-03-25 09:04:56 发布