51NOD - 1462树据结构

题目链接: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;
}
发布了809 篇原创文章 · 获赞 246 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/105249008
今日推荐