hdu3966(树链剖分)

时间:2024-03-26 16:34:32

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966

题意:一颗树上,每个点有权值,定义三种操作:

1)I操作表示从a到b节点之间的节点都加上一个值

2)D操作表示从a到b节点之间的节点的都减去一个权值

3)Q操作询问a节点当前的值。

分析:树链剖分裸题,在树上修改点权及询问点权,将树上信息映射到线段上后,就是一道水线段树题了。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct edge
{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}e[N<<];
int head[N<<],tot;
int top[N];//top[v]表示v所在的重链的顶端节点
int fa[N];//父亲节点
int dep[N];//深度
int sz[N];//si[v]表示以v为根节点的子树的节点数
int son[N];//重儿子
int p[N];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[N];//与p数组相反
int pos;//所有链构成的线段树总长度
int col[N<<],a[N];
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void init()
{
tot=;FILL(head,-);
pos=;FILL(son,-);
}
void dfs(int u,int f,int d)
{
dep[u]=d;sz[u]=;fa[u]=f;//printf("%d %d %d\n",u,f,d);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;//printf("%d\n\n",v);
if(v==f)continue;
dfs(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[son[u]]<sz[v])son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=++pos;
fp[pos]=u;
if(son[u]==-)return;
getpos(son[u],sp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
{
getpos(v,v);
}
}
} void Pushdown(int rt)
{
int ls=rt<<,rs=ls|;
if(col[rt])
{
col[rt<<]+=col[rt];
col[rt<<|]+=col[rt];
col[rt]=;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
col[rt]=a[fp[l]];
return;
}
int m=(l+r)>>;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]+=c;
return;
}
Pushdown(rt);
int m=(l+r)>>;
if(L<=m)update(L,R,c,lson);
if(m<R)update(L,R,c,rson);
}
int query(int ps,int l,int r,int rt)
{
if(l==r)
return col[rt];
Pushdown(rt);
int m=(l+r)>>;
if(ps<=m)return query(ps,lson);
if(ps>m)return query(ps,rson);
}
void lca(int u,int v,int c)
{
int fu=top[u],fv=top[v];
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
update(p[fu],p[u],c,,pos,);
u=fa[fu];fu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
update(p[u],p[v],c,,pos,);
}
int main()
{
int n,m,t,u,v,w;
while(scanf("%d%d%d",&n,&m,&t)>)
{
init();
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(,,);
getpos(,);
FILL(col,);
build(,pos,);
char op[];
while(t--)
{
scanf("%s",op);
if(op[]=='Q')
{
scanf("%d",&u);
printf("%d\n",query(p[u],,pos,));
}
else
{
scanf("%d%d%d",&u,&v,&w);
if(op[]=='D')w=-w;
lca(u,v,w);
}
}
}
}