hdu 3966(ツリーチェーン分割+ポイント権更新)
3519 ワード
題意:1本の木に、それぞれのポイント権の値を与え、3つの操作があります.
I C 1 C 2 K:C 1とC 2の経路上の全てのポイント重み値にKを加算
D C 1 C 2 K:C 1とC 2の経路上の全てのポイント重み値からKを減算
Q C:クエリーノード番号Cの重み値
問題を解く構想:この問題は明らかな木の鎖の断分問題で、ただここは点権の更新で、辺権の更新との違いに注意して、残りの基本はテンプレートです.
I C 1 C 2 K:C 1とC 2の経路上の全てのポイント重み値にKを加算
D C 1 C 2 K:C 1とC 2の経路上の全てのポイント重み値からKを減算
Q C:クエリーノード番号Cの重み値
問題を解く構想:この問題は明らかな木の鎖の断分問題で、ただここは点権の更新で、辺権の更新との違いに注意して、残りの基本はテンプレートです.
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 50010;
struct Segment
{
int l,r,sum,lazy;
}tree[maxn<<2];
struct Edge
{
int to,next;
}edge[maxn<<1];
int n,m,p,cnt,num,pre[maxn],A[maxn];
int top[maxn],son[maxn],size[maxn];
int fa[maxn],idx[maxn],dep[maxn];
void addedge(int u,int v)
{
edge[cnt].to = v;
edge[cnt].next = pre[u];
pre[u] = cnt++;
}
void dfs(int u)
{
size[u] = 1; son[u] = 0;
int tmp = 0;
for(int i = pre[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(fa[u] == v) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs(v);
size[u] += size[v];
if(size[v] > tmp)
{
tmp = size[v];
son[u] = v;
}
}
}
void build_tree(int u,int tp)
{
idx[u] = ++num; top[u] = tp;
if(son[u] != 0) build_tree(son[u],tp);
for(int i = pre[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(fa[u] == v || son[u] == v) continue;
build_tree(v,v);
}
}
void build_Segment(int rt,int l,int r)
{
tree[rt].l = l, tree[rt].r = r;
tree[rt].sum = tree[rt].lazy = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build_Segment(rt<<1,l,mid);
build_Segment(rt<<1|1,mid+1,r);
}
void PushDown(int rt)
{
if(tree[rt].lazy != 0)
{
tree[rt<<1].lazy += tree[rt].lazy;
tree[rt<<1].sum += tree[rt].lazy;
tree[rt<<1|1].lazy += tree[rt].lazy;
tree[rt<<1|1].sum += tree[rt].lazy;
tree[rt].lazy = 0;
}
}
void PushUp(int rt)
{
tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}
void update(int rt,int l,int r,int val)
{
if(l <= tree[rt].l && tree[rt].r <= r)
{
tree[rt].sum += val;
tree[rt].lazy += val;
return;
}
PushDown(rt);
int mid = (tree[rt].l + tree[rt].r) >> 1;
if(l <= mid) update(rt<<1,l,r,val);
if(mid < r) update(rt<<1|1,l,r,val);
PushUp(rt);
}
int query(int rt,int pos)
{
if(tree[rt].l == tree[rt].r)
return tree[rt].sum;
PushDown(rt);
int mid = (tree[rt].l + tree[rt].r) >> 1;
if(pos <= mid) return query(rt<<1,pos);
else return query(rt<<1|1,pos);
}
void Modify(int a,int b,int val)
{
int f1 = top[a], f2 = top[b];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(a,b);
}
update(1,idx[f1],idx[a],val);
a = fa[f1], f1 = top[a];
}
if(dep[a] > dep[b]) swap(a,b);
update(1,idx[a],idx[b],val);
}
int main()
{
int u,v,val;
char op[2];
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
memset(pre,-1,sizeof(pre));
cnt = num = 0;
dep[1] = 0;
for(int i = 1; i <= n; i++)
scanf("%d",&A[i]);
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1);
build_tree(1,1);
build_Segment(1,1,num);
for(int i = 1; i <= n; i++)
update(1,idx[i],idx[i],A[i]);
while(p--)
{
getchar();
scanf("%s",op);
if(op[0] == 'I')
{
scanf("%d%d%d",&u,&v,&val);
Modify(u,v,val);
}
else if(op[0] == 'D')
{
scanf("%d%d%d",&u,&v,&val);
Modify(u,v,-val);
}
else
{
scanf("%d",&u);
printf("%d
",query(1,idx[u]));
}
}
}
return 0;
}