题解:P2590 [ZJOI2008] 树的统计
思路
重链剖分板子题,用线段树维护剖分过的线性结构即可。
AC代码
#include<bits/stdc++.h>
#define ll long long
#define re register int
using namespace std;
const int maxn=30005;
const int inf=0x3f3f3f3f;
inline ll read()
{
ll x=0,f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return x*f;
}
ll tot=0;
ll w[maxn],b[maxn],d[maxn],fa[maxn];
ll siz[maxn],son[maxn],id[maxn],top[maxn];
struct node
{
ll nex,to;
}e[maxn<<1];ll head[maxn<<1],cnt=0;
struct dd
{
ll l,r,sum,maxx;
}t[maxn<<2];
inline void add(ll x,ll y)
{
e[++cnt].to=y;
e[cnt].nex=head[x];
head[x]=cnt;
}
inline void dfs1(ll x,ll f,ll deep)
{
siz[x]=1;
d[x]=deep;
fa[x]=f;
for(re i=head[x];i;i=e[i].nex)
{
ll y=e[i].to;
if(y==f)continue;
dfs1(y,x,deep+1);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y])
{
son[x]=y;
}
}
return;
}
inline void dfs2(ll x,ll top_)
{
id[x]=++tot;
b[tot]=w[x];
top[x]=top_;
if(!son[x])return;
dfs2(son[x],top_);
for(re i=head[x];i;i=e[i].nex)
{
ll y=e[i].to;
if(!id[y])dfs2(y,y);
}
return;
}
inline void push_up(ll x)
{
t[x].sum=t[x<<1].sum+t[x<<1|1].sum;
t[x].maxx=max(t[x<<1].maxx,t[x<<1|1].maxx);
}
inline void build(ll x,ll l,ll r)
{
t[x].l=l;t[x].r=r;
if(l==r)
{
t[x].sum=b[l];
t[x].maxx=b[l];
return;
}
ll mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
return;
}
inline void tree_change(ll x,ll l,ll r,ll q,ll v)
{
if(l==r)
{
t[x].sum=t[x].maxx=v;
return;
}
ll mid=(l+r)>>1;
if(q<=mid)tree_change(x<<1,l,mid,q,v);
else tree_change(x<<1|1,mid+1,r,q,v);
push_up(x);
}
inline ll querysum(ll x,ll l,ll r)
{
ll ans=0;
if(l<=t[x].l&&r>=t[x].r)
{
return t[x].sum;
}
ll mid=(t[x].l+t[x].r)>>1;
if(l<=mid)ans+=querysum(x<<1,l,r);
if(r>mid)ans+=querysum(x<<1|1,l,r);
return ans;
}
inline ll querymax(ll x,ll l,ll r)
{
ll ans=-inf;
if(l<=t[x].l&&r>=t[x].r)return t[x].maxx;
ll mid=(t[x].l+t[x].r)>>1;
if(l<=mid)ans=max(ans,querymax(x<<1,l,r));
if(r>mid)ans=max(ans,querymax(x<<1|1,l,r));
return ans;
}
inline ll tree_sum(ll u,ll v)
{
ll ans=0;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
ans+=querysum(1,id[top[u]],id[u]);
u=fa[top[u]];
}
if(d[u]>d[v])swap(u,v);
ans+=querysum(1,id[u],id[v]);
return ans;
}
inline ll tree_max(ll u,ll v)
{
ll ans=-inf;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
ans=max(ans,querymax(1,id[top[u]],id[u]));
u=fa[top[u]];
}
if(d[u]>d[v])swap(u,v);
ans=max(ans,querymax(1,id[u],id[v]));
return ans;
}
ll n,m;
int main()
{
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
n=read();
int x,y;
for(re i=1;i<n;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
for(re i=1;i<=n;i++)w[i]=read();
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
m=read();
for(re i=1;i<=m;i++)
{
char a[10];
cin>>a;
x=read();y=read();
if(a[1]=='H')
{
tree_change(1,1,n,id[x],y);
}
else if(a[1]=='M')
{
printf("%lld\n",tree_max(x,y));
}
else if(a[1]=='S')
{
printf("%lld\n",tree_sum(x,y));
}
}
return 0;
}

浙公网安备 33010602011771号