題意:給定樹和樹上每一個節點的權值 操作是修改一條路徑上所有點的權值
然後詢問點的權值是多少
解法:這一題初看的時候想到用splay解 但是用lct應該是更加簡單的
熟練剖分的話也可以的 因爲樹形沒有一點改變 然後用lct的時候其實就是在splay上打懶惰標記 這樣子我寫完之後就帶來了一個問題 那就是在這種情況下 我們執行access操作的時候是從該節點往上的 這樣子上一次的標記就不能下傳下來 然後我思考了一種暴力的方法 那就是在訪問一個節點的時候預先將其路徑上的根找到 然後我們進行標記的下傳就可以了
然後正解應該也是這個
這讓我想起了以前所寫的splay 大多都是有find操作的 這種情況下 也是自頂向下進行的更新 那麼對於直接能夠找到節點的元素 我們是不是也應該採用這種方法進行更新呢 但是這樣一來 我們所依賴的大概就是splay的旋轉來進行神奇的複雜度平衡了 如果把它當作一顆平衡樹來看的話 的卻應該是這樣的(事實上 splay的卻是一顆平衡樹)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ls ch[rt][0]
#define rs ch[rt][1]
#define maxn 55555
int ch[maxn][2],fa[maxn],_rt[maxn],val[maxn],add[maxn];
inline void down(int rt){
if(add[rt]){
if(ls)val[ls]+=add[rt],add[ls]+=add[rt];
if(rs)val[rs]+=add[rt],add[rs]+=add[rt];
add[rt]=0;
}
}
inline void _vis(int rt){
if(!_rt[rt])_vis(fa[rt]);
down(rt);
}
inline void rot(int rt){
int f=fa[rt],side=ch[f][1]==rt,ll=ch[rt][!side];
fa[ll]=f,ch[f][side]=ll;
fa[rt]=fa[f];
if(_rt[f])_rt[rt]=1,_rt[f]=0;
else ch[fa[f]][ch[fa[f]][1]==f]=rt;
fa[f]=rt,ch[rt][!side]=f;
}
inline void splay(int rt){
_vis(rt);
while(!_rt[rt]){
down(rt);
int f=fa[rt],ff=fa[f];
if(_rt[f])rot(rt);
else if((ch[f][1]==rt)==(ch[ff][1]==f))rot(f),rot(rt);
else rot(rt),rot(rt);
}
}
inline int ace(int rt){
int y=0;
for(;rt;y=rt,rt=fa[rt]){
splay(rt);
_rt[rs]=1,rs=y,_rt[rs]=0;
}return y;
}
inline void lca(int &u,int &v){
ace(v);v=0;
for(;u;v=u,u=fa[u]){
splay(u);
if(!fa[u])return ;
_rt[ch[u][1]]=1,ch[u][1]=v,_rt[v]=0;
}
}
inline void ins(int u,int v,int w){
lca(u,v);
val[u]+=w;
if(ch[u][1])val[ch[u][1]]+=w,add[ch[u][1]]+=w;
val[v]+=w,add[v]+=w;
}
char op[111];
int a,b,c,u,v,n,m,tot,head[maxn];
struct edge{int v,next;}e[maxn<<1];
inline void init(){memset(head,-1,sizeof head);tot=0;}
inline void adde(int u,int v){
e[tot].next=head[u];head[u]=tot,e[tot].v=v;
++tot;
}
void dfs(int u,int f){
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==f)continue;
fa[v]=u;
dfs(v,u);
}
}
int main(){
while(~scanf("%d%d%d",&n,&a,&m)){
for(int i=1;i<=n;++i)scanf("%d",&val[i]);
init();
for(int i=1;i<n;++i){
scanf("%d%d",&u,&v);
adde(u,v);adde(v,u);
}
for(int rt=0;rt<=n;++rt){
add[rt]=fa[rt]=ls=rs=0;_rt[rt]=1;
}dfs(1,-1);
val[0]=0;
while(m--){
scanf("%s%d",op,&a);
if(*op=='Q'){
ace(a),printf("%d\n",val[a]);}
else{
scanf("%d%d",&b,&c);
if(*op=='D')c=-c;
ins(a,b,c);
}
}
}
return 0;
}