题目链接:51NOD - 1462树据结构
因为有两个数据,线段树不好下放lazy标记。
所以我们直接转化为矩阵乘法即可。
每次乘不同的矩阵,具体是什么矩阵,自己推一推即可。
然后再树剖一下。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m,pos[N],son[N],dep[N],sz[N],bl[N],f[N],cnt,res[N],dfn[N];
vector<int> g[N];
struct mat{
int g[3][3];
mat(){memset(g,0,sizeof g);}
mat(int x){memset(g,0,sizeof g); for(int i=0;i<3;i++) g[i][i]=1;}
inline int empty(){return !g[0][1]&&!g[0][2]&&!g[1][2];}
inline void clear(){g[0][1]=g[0][2]=g[1][2]=0;}
friend mat mul(mat &a,mat &b){
mat c(1);
c.g[0][1]=a.g[0][1]+b.g[0][1];
c.g[0][2]=b.g[0][2]+a.g[0][1]*b.g[1][2]+a.g[0][2];
c.g[1][2]=a.g[1][2]+b.g[1][2];
return c;
}
}lazy[N<<2];
void dfs1(int x){
sz[x]=1;
for(auto to:g[x]) if(to!=f[x]){
f[to]=x; dep[to]=dep[x]+1;
dfs1(to); sz[x]+=sz[to];
if(sz[to]>sz[son[x]]) son[x]=to;
}
}
void dfs2(int x,int belong){
pos[x]=++cnt; dfn[cnt]=x; bl[x]=belong;
if(son[x]) dfs2(son[x],belong);
for(auto to:g[x]) if(dep[to]>dep[x]&&son[x]!=to) dfs2(to,to);
}
inline void push_down(int p){
if(lazy[p].empty()) return ;
lazy[p<<1]=mul(lazy[p<<1],lazy[p]);
lazy[p<<1|1]=mul(lazy[p<<1|1],lazy[p]);
lazy[p].clear();
}
void change(int p,int l,int r,int ql,int qr,mat &v){
if(l==ql&&r==qr){lazy[p]=mul(lazy[p],v); return ;}
int mid=l+r>>1; push_down(p);
if(qr<=mid) change(p<<1,l,mid,ql,qr,v);
else if(ql>mid) change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
inline void upd(int x,int y,int op,int d){
mat c(1);
(op==1?c.g[0][1]:c.g[1][2])=d;
while(bl[x]!=bl[y]){
if(dep[bl[x]]<dep[bl[y]]) swap(x,y);
change(1,1,n,pos[bl[x]],pos[x],c); x=f[bl[x]];
}
if(pos[x]>pos[y]) swap(x,y);
change(1,1,n,pos[x],pos[y],c);
}
void out(int p,int l,int r){
if(l==r){res[dfn[l]]=lazy[p].g[0][2]; return ;}
int mid=l+r>>1; push_down(p);
out(p<<1,l,mid),out(p<<1|1,mid+1,r);
}
signed main(){
cin>>n;
for(int i=2,x;i<=n;i++) scanf("%lld",&x),g[x].push_back(i);
dfs1(1); dfs2(1,1); cin>>m;
for(int i=1,op,u,d;i<=m;i++) scanf("%lld %lld %lld",&op,&u,&d),upd(1,u,op,d);
out(1,1,n);
for(int i=1;i<=n;i++) printf("%lld\n",res[i]);
return 0;
}