【BZOJ1036】[ZJOI2008]树的统计Count

时间:2021-10-31 00:51:15

大致(一句话)题意:树上单点修改权值+查询两点路径间权值最大值和权值和。

树链剖分模板题。。。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 30009
using namespace std;
int n,m,number=0,cnt=0,first[N],father[N],top[N],dfn[N],size[N],Mson[N],sum[N*4],Max[N*4],deep[N];
struct edge
{
int to,next;
void add(int x,int y)
{
to=y,next=first[x],first[x]=number;
}
}e[2*N];
void dfs1(int x)
{
size[x]=1;
deep[x]=deep[father[x]]+1;
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=father[x])
{
father[e[i].to]=x;
dfs1(e[i].to);
size[x]+=size[e[i].to];
if (size[e[i].to]>size[Mson[x]])
Mson[x]=e[i].to;
}
}
void dfs2(int x,int y)
{
dfn[x]=++cnt;
top[x]=y;
if (Mson[x]) dfs2(Mson[x],y);
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=father[x]&&e[i].to!=Mson[x])
dfs2(e[i].to,e[i].to);
}
void ins(int l,int r,int now,int x,int k)
{
if (l==r)
{
sum[k]=x;
Max[k]=x;
return;
}
int mid=l+r>>1;
if (mid>=now)
ins(l,mid,now,x,k<<1);
else
ins(mid+1,r,now,x,k<<1|1);
sum[k]=sum[k<<1]+sum[k<<1|1];
Max[k]=max(Max[k<<1],Max[k<<1|1]);
}
int qry_max(int l,int r,int L,int R,int k)
{
if (L<=l&&R>=r) return Max[k];
int mid=l+r>>1;
int ans=-126498716;
if (L<=mid) ans=max(ans,qry_max(l,mid,L,R,k<<1));
if (R>mid) ans=max(ans,qry_max(mid+1,r,L,R,k<<1|1));
return ans;
}
int qry_sum(int l,int r,int L,int R,int k)
{
if (L<=l&&R>=r) return sum[k];
int mid=l+r>>1;
int ans=0;
if (L<=mid) ans+=qry_sum(l,mid,L,R,k<<1);
if (R>mid) ans+=qry_sum(mid+1,r,L,R,k<<1|1);
return ans;
}
int qry(int x,int y,int pd)
{
int ans;
if (pd) ans=0;
else ans=-126498716;
for (;top[x]!=top[y];x=father[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
if (pd) ans+=qry_sum(1,n,dfn[top[x]],dfn[x],1);
else ans=max(ans,qry_max(1,n,dfn[top[x]],dfn[x],1));
}
if (dfn[y]>dfn[x]) swap(x,y);
if (pd) ans+=qry_sum(1,n,dfn[y],dfn[x],1);
else ans=max(ans,qry_max(1,n,dfn[y],dfn[x],1));
return ans;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[++number].add(x,y);
e[++number].add(y,x);
}
deep[0]=0;
father[1]=0;
dfs1(1);
dfs2(1,1);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
ins(1,n,dfn[i],x,1);
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
char ch[10];
int x,y;
scanf("%s%d%d",ch+1,&x,&y);
if (ch[1]=='C') ins(1,n,dfn[x],y,1);
else if (ch[2]=='M') printf("%d\n",qry(x,y,0));
else printf("%d\n",qry(x,y,1));
}
return 0;
}