裸树剖,注意多组数据和初始化的问题就好了。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=5e4+10;
struct edge{
int to,next;
}e[maxn<<1];
int head[maxn<<1],cnt=0;
int n;//节点数目
int d[maxn];//d[i]表示第i个结点的深度
int fa[maxn];//fa[i]表示第i个结点的parent
int son[maxn];//son[i]表示第i个结点的重子节点
int tot[maxn];//tot[i]表示以第i个结点为根节点的子树结点个数
int top[maxn];//top[i]表示第i个结点所在重链的顶部节点
int idx[maxn];//idx[i]表示第i个结点对应的dfs序
int a[maxn];//a[i]表示dfs序为i的结点的初值
int w[maxn];//w[i]表示第i个结点的初值
int ct=0;//辅助记录idx和a,没啥用
int m,r;//m次询问,r为树的根
void add_edge(int u,int v)
{
cnt++;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
struct node{
int left,right;
int lazy;
int sum;
int siz;
}tree[maxn<<2];
void pushup(int root)
{
tree[root].sum=(tree[root<<1].sum+tree[root<<1|1].sum);
}
void pushdown(int root)
{
if(!tree[root].lazy) return;
tree[root<<1].sum=(tree[root<<1].sum+tree[root].lazy*tree[root<<1].siz);
tree[root<<1|1].sum=(tree[root<<1|1].sum+tree[root].lazy*tree[root<<1|1].siz);
tree[root<<1].lazy=(tree[root<<1].lazy+tree[root].lazy);
tree[root<<1|1].lazy=(tree[root<<1|1].lazy+tree[root].lazy);
tree[root].lazy=0;
}
void build(int root,int left,int right)
{
tree[root].left=left,tree[root].right=right;
tree[root].siz=right-left+1;
if(left==right){
tree[root].sum=a[left];
return;
}
int mid=(left+right)>>1;
build(root<<1,left,mid);
build(root<<1|1,mid+1,right);
pushup(root);
}
void add(int root,int left,int right,int val)
{
if(left<=tree[root].left&&tree[root].right<=right){
tree[root].sum=(tree[root].sum+tree[root].siz*val);
tree[root].lazy=(tree[root].lazy+val);
return;
}
pushdown(root);
if(tree[root<<1].right>=left) add(root<<1,left,right,val);
if(tree[root<<1|1].left<=right) add(root<<1|1,left,right,val);
pushup(root);
}
int search(int root,int left,int right)
{
if(left<=tree[root].left&&tree[root].right<=right) return tree[root].sum;
pushdown(root);
int res=0;
if(tree[root<<1].right>=left) res=(res+search(root<<1,left,right));
if(tree[root<<1|1].left<=right) res=(res+search(root<<1|1,left,right));
return res;
}
int dfs1(int now,int pre,int dep)
{
d[now]=dep;
fa[now]=pre;
tot[now]=1;
int mxson=-1;
for(int i=head[now];i;i=e[i].next){
int nxt=e[i].to;
if(nxt==pre) continue;
tot[now]+=dfs1(nxt,now,dep+1);
if(tot[nxt]>mxson) mxson=tot[nxt],son[now]=nxt;
}
return tot[now];
}
void dfs2(int now,int topf)
{
idx[now]=++ct;
a[ct]=w[now];
top[now]=topf;
if(!son[now]) return;
dfs2(son[now],topf);
for(int i=head[now];i;i=e[i].next){
int nxt=e[i].to;
if(nxt==fa[now]||nxt==son[now]) continue;
dfs2(nxt,nxt);
}
}
void tree_add(int x,int y,int val)
{
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
add(1,idx[top[x]],idx[x],val);
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);
add(1,idx[x],idx[y],val);
}
int tree_sum(int x,int y)
{
int res=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
res=(res+search(1,idx[top[x]],idx[x]));
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);
res=(res+search(1,idx[x],idx[y]));
return res;
}
void updTree(int x,int val)
{
add(1,idx[x],idx[x]+tot[x]-1,val);
}
int askTree(int x)
{
return search(1,idx[x],idx[x]+tot[x]-1);
}
void init()
{
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
memset(tree,0,sizeof(tree));
cnt=ct=0;
}
int main()
{
int M;
while(~scanf("%d%d%d",&n,&M,&m)){
init();
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
r=1;
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--){
char opt[2];scanf("%s",opt);
int x,y,z;
int ans;
if(opt[0]=='I'){
scanf("%d%d%d",&x,&y,&z);
tree_add(x,y,z);
}
else if(opt[0]=='D'){
scanf("%d%d%d",&x,&y,&z);
tree_add(x,y,-z);
}
else if(opt[0]=='Q'){
scanf("%d",&x);
int ans=search(1,idx[x],idx[x]);
printf("%d\n",ans);
}
}
}
}