CF396C 题解
思路
对于一个点维护 \(b_i=a_i-a_{fa_i}\)。对于操作一,等价于 \(b_u\) 加 \(x\),\(u\) 的子树不含 \(u\) 的每个点和父亲的差都减 \(k\)。对于操作二,等价于从根到 \(u\) 路径上的 \(b_x\) 的和。同 P3178,子树加,路径查,树剖加线段树。
code
int n,q;
int head[maxn],tot;
struct nd{
int nxt,to;
}e[maxn];
void add(int u,int v){e[++tot]={head[u],v};head[u]=tot;}
int fa[maxn],siz[maxn],son[maxn],dep[maxn];
void dfs(int u){
siz[u]=1;dep[u]=dep[fa[u]]+1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;if(v==fa[u])continue;
fa[v]=u;dfs(v);siz[u]+=siz[v];
if(siz[v]>=siz[son[u]])son[u]=v;
}
}
int dfn[maxn],idx,tp[maxn];
void dfs1(int u,int lst){
dfn[u]=++idx;tp[u]=lst;
if(!son[u])return ;
dfs1(son[u],lst);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;if(v==fa[u]||v==son[u])continue;
dfs1(v,v);
}
}
int tree[maxn<<2],tag[maxn<<2];
#define mid (l+r>>1)
#define ls nd<<1
#define rs nd<<1|1
void push(int nd,int l,int r){
if(tag[nd]){
(tree[ls]+=1ll*(mid-l+1)*tag[nd]%mod)%=mod;(tag[ls]+=tag[nd])%=mod;
(tree[rs]+=1ll*(r-mid)*tag[nd]%mod)%=mod;(tag[rs]+=tag[nd])%=mod;
tag[nd]=0;
}
}
void updata(int nd,int l,int r,int ql,int qr,int w){
if(ql>qr)return ;
if(l>=ql&&r<=qr){
(tree[nd]+=1ll*(r-l+1)*w%mod)%=mod;(tag[nd]+=w)%=mod;
return ;
}
push(nd,l,r);
if(ql<=mid)updata(ls,l,mid,ql,qr,w);
if(qr>mid)updata(rs,mid+1,r,ql,qr,w);
tree[nd]=(tree[ls]+tree[rs])%mod;
}
int query(int nd,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return tree[nd];
push(nd,l,r);
if(qr<=mid)return query(ls,l,mid,ql,qr);
if(ql>mid)return query(rs,mid+1,r,ql,qr);
return (query(ls,l,mid,ql,qr)+query(rs,mid+1,r,ql,qr))%mod;
}
int que(int u){
int res=0;
while(u){
(res+=query(1,1,n,dfn[tp[u]],dfn[u]))%=mod;
u=fa[tp[u]];
}
return res;
}
void work(){
n=read();
for(int i=2;i<=n;i++){int p=read();add(p,i);}
dfs(1),dfs1(1,1);
q=read();
while(q--){
int op=read();
if(op==1){
int u=read(),x=read(),k=read();
updata(1,1,n,dfn[u]+1,dfn[u]+siz[u]-1,mod-k);
updata(1,1,n,dfn[u],dfn[u],x);
}
else{
int u=read();
printf("%d\n",que(u));
}
}
}