Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
Input
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
树剖裸题 刷水题吼啊
这题是一个裸的点权,不用转边权做.大水题
单点修改,(tag)都不用打.qwq
线段树维护区间最大值,区间和。
单点修改要对(dfn)修改!! (本来要切掉的,结果这里写错了.
代码
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#define int long long
#define R register
#define ls o<<1
#define rs o<<1|1
#define N 30008
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int head[N],tot,depth[N],size[N],f[N],son[N];
struct cod{int u,v;}edge[N<<1];
int dfn[N],idx,fdfn[N],top[N];
int n,a[N],m,tr[N<<2],mx[N<<2];
char s[18];
inline void add(int x,int y)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
inline void up(int o)
{
tr[o]=tr[ls]+tr[rs];
mx[o]=max(mx[ls],mx[rs]);
}
void build(int o,int l,int r)
{
if(l==r)
{
mx[o]=tr[o]=a[fdfn[l]];
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(o);
}
int query_sum(int o,int l,int r,int x,int y)
{
if(x<=l and y>=r)return tr[o];
int mid=(l+r)>>1,res=0;
if(x<=mid)res+=query_sum(ls,l,mid,x,y);
if(y>mid)res+=query_sum(rs,mid+1,r,x,y);
return res;
}
int query_max(int o,int l,int r,int x,int y)
{
if(x<=l and y>=r)return mx[o];
int mid=(l+r)>>1,res=-2147483647;
if(x<=mid)res=max(res,query_max(ls,l,mid,x,y));
if(y>mid)res=max(res,query_max(rs,mid+1,r,x,y));
return res;
}
void change(int o,int l,int r,int pos,int k)
{
if(l==r){mx[o]=tr[o]=k;return;}
int mid=(l+r)>>1;
if(pos<=mid)change(ls,l,mid,pos,k);
else change(rs,mid+1,r,pos,k);
up(o);
}
void dfs1(int u,int fa)
{
size[u]=1;f[u]=fa;depth[u]=depth[fa]+1;
for(R int i=head[u];i;i=edge[i].u)
{
if(edge[i].v==fa)continue;
dfs1(edge[i].v,u);
size[u]+=size[edge[i].v];
if(son[u]==-1 or size[son[u]]<size[edge[i].v])
son[u]=edge[i].v;
}
}
void dfs2(int u,int t)
{
dfn[u]=++idx;fdfn[idx]=u;top[u]=t;
if(son[u]==-1)return;
dfs2(son[u],t);
for(R int i=head[u];i;i=edge[i].u)
{
if(dfn[edge[i].v])continue;
dfs2(edge[i].v,edge[i].v);
}
}
int tquery(int x,int y)
{
int fx=top[x],fy=top[y],res=0;
while(fx!=fy)
{
if(depth[fx]>depth[fy])
{
res+=query_sum(1,1,idx,dfn[fx],dfn[x]);
x=f[fx];
}
else
{
res+=query_sum(1,1,idx,dfn[fy],dfn[y]);
y=f[fy];
}
fx=top[x],fy=top[y];
}
if(dfn[x]>dfn[y])swap(x,y);
res+=query_sum(1,1,idx,dfn[x],dfn[y]);
return res;
}
int tquery_max(int x,int y)
{
int fx=top[x],fy=top[y],res=-2147483647;
while(fx!=fy)
{
if(depth[fx]>depth[fy])
{
res=max(res,query_max(1,1,idx,dfn[fx],dfn[x]));
x=f[fx];
}
else
{
res=max(res,query_max(1,1,idx,dfn[fy],dfn[y]));
y=f[fy];
}
fx=top[x],fy=top[y];
}
if(dfn[x]>dfn[y])swap(x,y);
res=max(res,query_max(1,1,idx,dfn[x],dfn[y]));
return res;
}
signed main()
{
in(n);memset(son,-1,sizeof son);
for(R int i=1,x,y;i<n;i++)
{
in(x),in(y);
add(x,y);add(y,x);
}
dfs1(1,0);dfs2(1,1);
for(R int i=1;i<=n;i++)in(a[i]);
build(1,1,n);
in(m);
for(R int x,y;m;m--)
{
scanf("%s",s);in(x),in(y);
if(s[3]=='X')
printf("%lld
",tquery_max(x,y));
else if(s[3]=='M')
printf("%lld
",tquery(x,y));
else
change(1,1,idx,dfn[x],y);
}
}