题目大意:给定一棵树,两两种操作,一种是询问v,u所有节点的sum,还有一种是修改u到v上所有路径的val;
题目解析:裸的树链剖分;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=50010;
struct edge
{
int to,next;
}e[maxn<<1];
int head[maxn],tot;
int num[maxn];//叶子节点的值
int size[maxn];//儿子个数
int top[maxn];//当前节点所在链的顶端节点
int son[maxn];//重儿子
int dep[maxn];//深度
int tid[maxn];//被树剖之后的新编号
int rak[maxn];//当前节点在线段树间的位置
int fa[maxn];//父亲
int tim;
void init()
{
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
tim=0;
tot=0;
}
void addedge(int u,int v)
{
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
e[tot].to=u;
e[tot].next=head[v];
head[v]=tot++;
}
void dfs1(int u,int father,int d)
{
dep[u]=d;
fa[u]=father;
size[u]=1;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=father)
{
dfs1(v,u,d+1);
size[u]+=size[v];
if(son[u]==-1||size[v]>size[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
tid[u]=++tim;
rak[tid[u]]=u;
if(son[u]==-1) return ;
dfs2(son[u],tp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
{
dfs2(v,v);
}
}
}
//线段树
int sum[maxn<<2],col[maxn<<2],n,m,q;
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int m)
{
if(col[rt])
{
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
sum[rt<<1]+=(m-(m>>1))*col[rt];
sum[rt<<1|1]+=(m>>1)*col[rt];
col[rt]=0;
}
}
void build(int l,int r,int rt)
{
col[rt]=0;
if(l==r)
{
sum[rt]=num[rak[l]];
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int le,int ri,int v,int l,int r,int rt)
{
//cout<<le<<" "<<ri<<" "<<l<<" "<<r<<endl;
if(le<=l&&ri>=r)
{
col[rt]+=v;
sum[rt]+=v*(r-l+1);
return ;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
int ret=0;
if(le<=mid) update(le,ri,v,lson);
if(ri>mid) update(le,ri,v,rson);
pushup(rt);
}
int query(int le,int ri,int l,int r,int rt)
{
if(le<=l&&ri>=r)
return sum[rt];
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
int ret=0;
if(le<=mid) ret+=query(le,ri,lson);
if(ri>mid) ret+=query(le,ri,rson);
pushup(rt);
return ret;
}
void change(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(tid[top[x]],tid[x],val,1,n,1);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(tid[x],tid[y],val,1,n,1);
}
int main()
{
char op[5];
int a,b,c;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
init();
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
dfs1(1,0,0);
dfs2(1,1);
build(1,n,1);
while(q--)
{
scanf("%s",&op[0]);
if(op[0]=='Q')
{
scanf("%d",&a);
printf("%d\n",query(tid[a],tid[a],1,n,1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
if(op[0]=='D')
{
c=-c;
}
change(a,b,c);
}
}
}
return 0;
}