/*
HDU 3966
题意:
给n个结点,m条边,p次操作
I x y k
D x y k
x->y的路径上的节点都增加或减少k
Q x 查询x结点的权值
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50010;
int val[maxn],cnt,head[maxn],n;
int d[maxn],f[maxn],sz[maxn],son[maxn],top[maxn],id[maxn],tot,rk[maxn];
int t[maxn<<2],a[maxn],add[maxn<<2];
/*建图*/
struct node
{
int to,next;
} e[maxn<<1];
void Init()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(son,-1,sizeof(son));
tot=0;
}
void addEdge(int u,int v)
{
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
/*树链剖分*/
void dfs1(int u,int fa,int depth)
{
f[u]=fa;
d[u]=depth;
sz[u]=1;
for(int i=head[u]; ~i; i=e[i].next)
{
int v=e[i].to;
if(v!=f[u])
{
dfs1(v,u,depth+1);
sz[u]+=sz[v];
if(son[u]==-1||sz[son[u]]<sz[v])
son[u]=v;
}
}
}
void dfs2(int u,int tp)/*重新编号*/
{
top[u]=tp;
id[u]=++tot;
rk[id[u]]=u;/*记录数组的第i个位置是编号为几的数*/
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!=f[u]&&v!=son[u])
dfs2(v,v);
}
}
/*线段树*/
void pushup(int cur)
{
t[cur]=t[cur<<1]+t[cur<<1|1];
}
void pushdown(int cur,int l,int r)
{
int mid=(l+r)>>1;
if(add[cur])
{
add[cur<<1]+=add[cur];
add[cur<<1|1]+=add[cur];
t[cur<<1]+=add[cur]*(mid-l+1);
t[cur<<1|1]+=add[cur]*(r-mid);
add[cur]=0;
}
}
void build(int cur,int l,int r)
{
add[cur]=0;
if(l==r)
{
t[cur]=val[rk[l]];
return ;
}
int mid=(l+r)>>1;
build(cur<<1,l,mid);
build(cur<<1|1,mid+1,r);
}
void Update(int cur,int l,int r,int L,int R,int k)
{
if(L<=l&&R>=r)
{
add[cur]+=k;
t[cur]+=(r-l+1)*k;
return ;
}
pushdown(cur,l,r);
int mid=(l+r)>>1;
if(L<=mid)
Update(cur<<1,l,mid,L,R,k);
if(R>mid)
Update(cur<<1|1,mid+1,r,L,R,k);
pushup(cur);
}
int Query(int cur,int l,int r,int index)
{
int ans;
if(l==r)
return t[cur];
pushdown(cur,l,r);
int mid=(l+r)>>1;
if(index<=mid)
ans=Query(cur<<1,l,mid,index);
else ans=Query(cur<<1|1,mid+1,r,index);
// pushup(cur);
return ans;
}
void Change(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])
swap(x,y);
Update(1,1,n,id[top[x]],id[x],val);
x=f[top[x]];
}
if(d[x]>d[y])
swap(x,y);
Update(1,1,n,id[x],id[y],val);
}
int main()
{
int m,p,u,v,y,x,k;
char s[110];
while(~scanf("%d%d%d",&n,&m,&p))
{
Init();
for(int i=1; i<=n; i++)
scanf("%d",&val[i]);
for(int i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
while(p--)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",Query(1,1,n,id[x]));
}
else
{
scanf("%d%d%d",&x,&y,&k);
if(s[0]=='D')
k=-k;
Change(x,y,k);
}
}
}
return 0;
}
/*
10 9 5
1 2 3 4 5 6 7 8 9 10
1 2
1 3
2 8
3 5
3 4
5 7
5 6
4 9
9 10
*/
/*FZU 2082 更新边权*/
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
const int maxn=50010;
struct node
{
int to,next,w,id;
} e[maxn<<1];
int n,head[maxn],cnt,f[maxn],d[maxn],son[maxn],sz[maxn],val[maxn],ee[maxn],tot,top[maxn],id[maxn],rk[maxn];
void Init()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(son,-1,sizeof(son));
tot=0;
}
void add(int u,int v,int w,int id)
{
e[cnt].to=v;
e[cnt].w=w;
e[cnt].id=id;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs1(int u,int fa,int depth,int w,int pos)
{
f[u]=fa;/*记录父亲*/
d[u]=depth;/*记录深度*/
sz[u]=1;/*记录孩子个数,选择重边*/
val[u]=w;/*以u为终点的边的权值为w*/
ee[pos]=u;/*第pos条边的终点为u*/
for(int i=head[u]; ~i; i=e[i].next)
{
int v=e[i].to;
if(v!=fa)
{
dfs1(v,u,depth+1,e[i].w,e[i].id);
sz[u]+=sz[v];
if(son[u]==-1||sz[son[u]]<sz[v])
son[u]=v;
}
}
}
void dfs2(int u,int tp)/*将同一条链的结点映射到连续的一段区间[]*/
{
top[u]=tp;
id[u]=++tot;
rk[id[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!=f[u]&&v!=son[u])
dfs2(v,v);
}
}
/*线段树 单点更新 区间查询*/
LL t[maxn<<2];
void pushup(int cur)
{
t[cur]=t[cur<<1]+t[cur<<1|1];
}
void build(int cur,int l,int r)
{
if(l==r)
{
t[cur]=val[rk[l]];
return ;
}
int mid=(l+r)>>1;
build(cur<<1,l,mid);
build(cur<<1|1,mid+1,r);
pushup(cur);
}
void Update(int cur,int l,int r,int index,int k)
{
if(l==r)
{
t[cur]=k;
return ;
}
int mid=(l+r)>>1;
if(index<=mid)
Update(cur<<1,l,mid,index,k);
else Update(cur<<1|1,mid+1,r,index,k);
pushup(cur);
}
LL Query(int cur,int l,int r,int L,int R)
{
LL ans=0;
if(L<=l&&R>=r)
{
return t[cur];
}
int mid=(l+r)>>1;
if(L<=mid)
ans+=Query(cur<<1,l,mid,L,R);
if(R>mid)
ans+=Query(cur<<1|1,mid+1,r,L,R);
return ans;
}
void Change(int u,int v)
{
LL ans=0;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])
swap(u,v);
ans+=Query(1,1,n,id[top[u]],id[u]);
u=f[top[u]];
}
if(d[u]>d[v])
swap(u,v);
ans+=Query(1,1,n,id[u]+1,id[v]);
printf("%lld\n",ans);
}
int main()
{
int m,u,v,w,op,x,y;
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=1; i<n; i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w,i);
add(v,u,w,i);
}
dfs1(1,0,0,0,0);
dfs2(1,1);
build(1,1,n);
while(m--)
{
scanf("%d%d%d",&op,&x,&y);
if(op==0)
{
Update(1,1,n,id[ee[x]],y);
}
else
{
Change(x,y);
}
}
}
return 0;
}
//BZOJ 1036 更新点权
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=30010;
int val[maxn],n;
int head[maxn],cnt,d[maxn],f[maxn],sz[maxn],son[maxn],id[maxn],tot,rk[maxn],top[maxn];
struct node
{
int to,next;
} e[maxn<<1];
struct pp
{
int sum,Max;
} t[maxn<<2];
void Init()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(son,-1,sizeof(son));
tot=0;
}
void addEdge(int u,int v)
{
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs1(int u,int fa,int depth)
{
d[u]=depth;
f[u]=fa;
sz[u]=1;
for(int i=head[u]; ~i; i=e[i].next)
{
int v=e[i].to;
if(v!=fa)
{
dfs1(v,u,depth+1);
sz[u]+=sz[v];
if(son[u]==-1||sz[son[u]]<sz[v])
son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
id[u]=++tot;
rk[id[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!=f[u]&&son[u]!=v)
dfs2(v,v);
}
}
void pushup(int cur)
{
t[cur].sum=t[cur<<1].sum+t[cur<<1|1].sum;
t[cur].Max=max(t[cur<<1].Max,t[cur<<1|1].Max);
}
void build(int cur,int l,int r)
{
if(l==r)
{
t[cur].Max=t[cur].sum=val[rk[l]];
return ;
}
int mid=(l+r)>>1;
build(cur<<1,l,mid);
build(cur<<1|1,mid+1,r);
pushup(cur);
}
void Update(int cur,int l,int r,int index,int k)
{
if(l==r)
{
t[cur].Max=t[cur].sum=k;
return ;
}
int mid=(l+r)>>1;
if(index<=mid)
Update(cur<<1,l,mid,index,k);
else
Update(cur<<1|1,mid+1,r,index,k);
pushup(cur);
}
int Query(int cur,int l,int r,int L,int R,int flag)
{
// printf("l = %d r = %d\n",l,r);
int ans;
if(flag)
ans=-INF;/*数据权值有负数 之前设ans=0 WA*/
else ans=0;
if(L<=l&&R>=r)
{
if(flag)
return t[cur].Max;
else return t[cur].sum;
}
int mid=(l+r)>>1;
if(L<=mid)
{
if(flag)
ans=max(ans,Query(cur<<1,l,mid,L,R,flag));
else ans+=Query(cur<<1,l,mid,L,R,flag);
}
if(R>mid)
{
if(flag)
ans=max(ans,Query(cur<<1|1,mid+1,r,L,R,flag));
else ans+=Query(cur<<1|1,mid+1,r,L,R,flag);
}
return ans;//没返回值 debug了好久。。
}
void Change(int u,int v,int flag)
{
int ans;
if(flag)
ans=-INF;
else ans=0;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])
swap(u,v);
if(flag)ans=max(ans,Query(1,1,n,id[top[u]],id[u],flag));
else ans+=Query(1,1,n,id[top[u]],id[u],flag);
u=f[top[u]];
}
if(d[u]>d[v])
swap(u,v);
if(flag)
ans=max(ans,Query(1,1,n,id[u],id[v],flag));
else ans+=Query(1,1,n,id[u],id[v],flag);
printf("%d\n",ans);
}
int main()
{
int u,v,x,y,q;
char s[110];
scanf("%d",&n);
Init();
for(int i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
for(int i=1; i<=n; i++)
scanf("%d",&val[i]);
dfs1(1,0,0);
dfs2(1,1); //
build(1,1,n);
scanf("%d",&q);
while(q--)
{
scanf("%s",s);
if(s[0]=='C')
{
scanf("%d%d",&x,&y);
Update(1,1,n,id[x],y);
}
else
{
scanf("%d%d",&x,&y);
if(s[1]=='M')
Change(x,y,1);
else
Change(x,y,0);
}
}
return 0;
}