Solution Set - 矩阵加速

A[HDU2604]求不含子串010和000的,长为\(n\)的01序列数。
B[HDU6470]数列\(\{a_n\}:a_1=1,a_2=2,a_n=a_{n-1}+2a_{n-2}+n^3\),给定\(n\),求\(a_n\)
C[HDU3306]数列\(\{a_n\}:a_0=a_1=1,a_n=xa_{n-1}+ya_{n-2}\),给定\(n,x,y\),求前\(n\)项平方和。
D[HDU2276]01环,每轮操作改变所有1左边位置的值,求\(m\)轮后的结果。
E[LibreOJ#6208]给定一棵树,点有两个权\(k,t\),支持对某个点到根的路径修改\(k+d \to k\)\(t+k\times d \to t\),询问单点的\(t\)
F[LibreOJ#2980]给定三个数列\(a,b,c\),支持以下操作:\(a_i+b_i \to a_i\)\(b_i+c_i \to b_i\)\(c_i+a_i \to c_i\)\(a_i+v \to a_i\)\(b_i \times v \to b_i\)\(v \to c_i\),询问\(a,b,c\)的区间和。
G[CF750E]给定数字串,对某个子串,求其至少删去多少个字符,才能使剩余串含子序列2017,但不含子序列2016。
H[洛谷P6573]给定有向图,边有权,边\((x,y)\)满足\(\left\lfloor\dfrac{y}{k}\right\rfloor=1+\left\lfloor\dfrac{x}{k}\right\rfloor\)\(1\le k \le 5\)。求从\(u\)\(v\)的最小路程。多组询问。
I[洛谷P7359]给定树,每条边有距离\(a\),水流影响\(b\)以及水流向。通过一条边,走路耗时\(a\),顺流而下耗时\(a-b\),逆流而上耗时\(a+b\)。每次上船需要时间\(l\)。求从\(u\)\(v\)的最小时间。多组询问。
J[洛谷P4719]一棵树,点有权,单点修改,求最大权独立集。
K[洛谷P6021]一棵树,点有权,单点修改,求在某棵子树中选出一些点,使得所有叶子与根不连通的最小权值和。
L[洛谷P5024]一棵树,点有权,给定某两个点的选择状况,求最小权覆盖集。


A维护\(6\times6\)的矩阵,代表可能的\(6\)种结尾三个数。然后用矩阵快速幂。
B移项,求出一个三次函数\(f\)使\(a_n+f(n)=(a_{n-1}+f(n-1))+2(a_{n-2}+f(n-2))\),然后用矩阵快速幂求\(a_n+f(n)\)
C维护\(a_{n-1}^2,a_{n-2}^2,a_{n-1}a_{n-2},s_{n-1}\),矩阵快速幂。
D看做模2的加法,矩阵快速幂。
E用矩阵刻画修改,先做树链剖分,然后用线段树维护。
F和E类似,但不用树剖。
G先推暴力DP,状态定义为考虑到某个位置,已经匹配到201的第几个位置。然后从后往前找第一个7,它后面的6全部要删去,它前面要留下201。推完发现转移可以用矩阵刻画,然后就用线段树维护。
H每\(k\)个构建一个矩阵。
I矩阵维护在船上和不在船上两个状态,通过一条边的转移可以用矩阵刻画。倍增即可。

动态DP:(通常在树上)用矩阵刻画DP转移。做树链剖分,然后对每个点记录轻儿子的转移矩阵之积。修改时从一个点向上跳,修改每条轻边的贡献;询问是把1所在重链的矩阵相乘。

JKL都是模板。L要注意撤销修改时的顺序。


点击查看A题代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct Matrix{
	int a[6][6];
	Matrix (){memset(a,0,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<6;i++)
			for(int j=0;j<6;j++)
				for(int k=0;k<6;k++)
					c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%m)%m;
		return c;
	}
}t;
Matrix power(Matrix a,int b,Matrix c){
	for(;b;b>>=1){if(b&1)c=c*a;a=a*a;}
	return c;
}
int main(){
	//0ffm 1fmm 2mff 3mfm 4mmf 5mmm
	t.a[0][1]=1;t.a[1][4]=1;t.a[1][5]=1;t.a[2][0]=1;
	t.a[3][1]=1;t.a[4][2]=1;t.a[4][3]=1;t.a[5][4]=1;t.a[5][5]=1;
	while(scanf("%d%d",&n,&m)!=EOF){
		if(n<=3){
			if(n==0)printf("%d\n",1%m);
			if(n==1)printf("%d\n",2%m);
			if(n==2)printf("%d\n",4%m);
			if(n==3)printf("%d\n",6%m);
			continue;
		}
		Matrix c;
		c.a[0][0]=c.a[0][1]=c.a[0][2]=c.a[0][3]=c.a[0][4]=c.a[0][5]=1;
		c=power(t,n-3,c);
		printf("%d\n",(c.a[0][0]+c.a[0][1]+c.a[0][2]+
					   c.a[0][3]+c.a[0][4]+c.a[0][5])%m);
	}
	return 0;
}
点击查看B题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=123456789,inv8=46296296;
int T;ll n;
struct Matrix{
	int a[2][2];
	Matrix (){memset(a,0,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				for(int k=0;k<2;k++)
					c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%mod)%mod;
		return c;
	}
}t;
Matrix power(Matrix a,ll b,Matrix c){
	for(;b;b>>=1){if(b&1)c=c*a;a=a*a;}
	return c;
}
int main(){
	t.a[0][0]=0;t.a[0][1]=2;t.a[1][0]=t.a[1][1]=1;
	scanf("%d",&T);
	while(T--){
		scanf("%lld",&n);
		Matrix c;c.a[0][0]=277;c.a[0][1]=499;
		c=power(t,n-2,c);n%=mod;
		ll ans=(c.a[0][1]-(4*n%mod*n%mod*n%mod+30*n%mod*n%mod+96*n%mod+139)%mod
					+mod)%mod*inv8%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
点击查看C题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10007;
struct Matrix{
	ll a[4][4];
	Matrix (){memset(a,0,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
				for(int k=0;k<4;k++)
					c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
		return c;
	}
};
Matrix power(Matrix a,ll b,Matrix c){
	for(;b;b>>=1){if(b&1)c=c*a;a=a*a;}
	return c;
}
ll n,x,y;
int main(){
	while(scanf("%lld%lld%lld",&n,&x,&y)!=EOF){
		Matrix a,b;
		a.a[2][0]=1;a.a[2][1]=x%mod;a.a[1][1]=y%mod;
		a.a[0][3]=a.a[0][2]=y*y%mod;
		a.a[1][3]=a.a[1][2]=2*x%mod*y%mod;
		a.a[2][3]=a.a[2][2]=x*x%mod;a.a[3][3]=1;
		b.a[0][0]=b.a[0][1]=b.a[0][2]=1;b.a[0][3]=2;
		b=power(a,n-1,b);
		printf("%lld\n",b.a[0][3]);
	}
	return 0;
}
点击查看D题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,mod=2;
int n,m;char s[N];
struct Matrix{
	ll a[N][N];
	Matrix (){memset(a,0,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				for(int k=0;k<n;k++)
					c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
		return c;
	}
};
Matrix power(Matrix a,ll b,Matrix c){
	for(;b;b>>=1){if(b&1)c=c*a;a=a*a;}
	return c;
}
int main(){
	while(scanf("%d",&m)!=EOF){
		scanf("%s",s);n=strlen(s);
		Matrix a,b;
		for(int i=0;i<n;i++){
			a.a[0][i]=s[i]-'0';
			b.a[i][i]=b.a[i][(i+1)%n]=1;
		}
		a=power(b,m,a);
		for(int i=0;i<n;i++)printf("%d",a.a[0][i]);
		printf("\n");
	}
	return 0;
}
点击查看E题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m;
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
struct Matrix{
	ll a[3][3];
	Matrix (int op=1){memset(a,0,sizeof(a));if(op)a[0][0]=a[1][1]=a[2][2]=1;}
	Matrix operator *(const Matrix&b)const{
		Matrix c(0);
		for(int i=0;i<3;i++)
			for(int j=0;j<3;j++)
				for(int k=0;k<3;k++)
					c.a[i][j]+=a[i][k]*b.a[k][j];
		return c;
	}
}f,zero;
int fa[N],son[N],top[N],L[N],dfn,siz[N];
void dfs(int u){
	siz[u]=1;
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]){
			fa[v]=u;dfs(v);siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
		}
}
void rdfs(int u,int tp){
	L[u]=++dfn;top[u]=tp;
	if(son[u])rdfs(son[u],tp);
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]&&v!=son[u])rdfs(v,v);
}
struct SegmentTree{
	Matrix a[N<<2];
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void push_down(int p){
		a[ls]=a[ls]*a[p];a[rs]=a[rs]*a[p];
		a[p]=zero;
	}
	void modify(int p,int l,int r,int L,int R,Matrix v){
		if(l>=L&&r<=R){a[p]=a[p]*v;return;}
		push_down(p);
		if(L<=mid)modify(ls,l,mid,L,R,v);
		if(R>mid)modify(rs,mid+1,r,L,R,v);
	}
	Matrix query(int p,int l,int r,int x){
		if(l==r)return a[p];
		push_down(p);
		if(x<=mid)return query(ls,l,mid,x);
		else return query(rs,mid+1,r,x);
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
void update(int u,Matrix v){
	while(u){
		seg.modify(1,1,n,L[top[u]],L[u],v);
		u=fa[top[u]];
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1);rdfs(1,1);
	scanf("%d",&m);
	for(int i=1,op,u,v;i<=m;i++){
		scanf("%d%d",&op,&u);
		if(op<=2){
			scanf("%d",&v);
			if(op==1)f.a[2][0]=v,f.a[0][1]=0;
			else f.a[0][1]=v,f.a[2][0]=0;
			update(u,f);
		}
		else{
			Matrix ans(0);ans.a[0][2]=1;
			ans=ans*seg.query(1,1,n,L[u]);
			printf("%lld\n",ans.a[0][1]);
		}
	}
	return 0;
}
点击查看F题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2.5e5+5,mod=998244353;
int n,m;
struct Matrix{
	ll a[4][4];
	Matrix (int op=1){
		memset(a,0,sizeof(a));
		if(op)a[0][0]=a[1][1]=a[2][2]=a[3][3]=1;
	}
	Matrix operator +(const Matrix&b)const{
		Matrix c(0);
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
				c.a[i][j]=(a[i][j]+b.a[i][j])%mod;
		return c;
	}
	Matrix operator *(const Matrix&b)const{
		Matrix c(0);
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
				for(int k=0;k<4;k++)
					c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%mod;
		return c;
	}
}g[N],zero;
struct SegmentTree{
	Matrix sum[N<<2],tag[N<<2];
	void init(){
		for(int i=1;i<=n*4;i++){Matrix x(0);sum[i]=x;}
	}
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void push_up(int p){sum[p]=sum[ls]+sum[rs];}
	void push_down(int p){
		sum[ls]=sum[ls]*tag[p];sum[rs]=sum[rs]*tag[p];
		tag[ls]=tag[ls]*tag[p];tag[rs]=tag[rs]*tag[p];
		tag[p]=zero;
	}
	void build(int p,int l,int r){
		if(l==r){sum[p]=g[l];return;}
		build(ls,l,mid);build(rs,mid+1,r);
		push_up(p);
	}
	void modify(int p,int l,int r,int L,int R,Matrix v){
		if(l>=L&&r<=R){
			sum[p]=sum[p]*v;tag[p]=tag[p]*v;
			return;
		}
		push_down(p);
		if(L<=mid)modify(ls,l,mid,L,R,v);
		if(R>mid)modify(rs,mid+1,r,L,R,v);
		push_up(p);
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return sum[p];
		push_down(p);
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R);
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
int main(){
	scanf("%d",&n);
	for(int i=1,a,b,c;i<=n;i++){
		scanf("%d%d%d",&a,&b,&c);
		Matrix x(0);x.a[0][0]=a;x.a[0][1]=b;x.a[0][2]=c;x.a[0][3]=1;
		g[i]=x;
	}
	seg.init();seg.build(1,1,n);
	scanf("%d",&m);
	for(int i=1,op,l,r,v;i<=m;i++){
		scanf("%d%d%d",&op,&l,&r);
		Matrix f;
		if(op==7){
			f=seg.query(1,1,n,l,r);
			printf("%lld %lld %lld\n",f.a[0][0],f.a[0][1],f.a[0][2]);
		}
		else{
			if(op<=3)f.a[op%3][op-1]=1;
			else{
				scanf("%d",&v);
				if(op==4)f.a[3][0]=v;
				if(op==5)f.a[1][1]=v;
				if(op==6)f.a[2][2]=0,f.a[3][2]=v;
			}
			seg.modify(1,1,n,l,r,f);
		}
	}
	return 0;
}
点击查看G题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,INF=1e9+7;
int n,m,cnt[N],lst[N];char s[N];
struct Matrix{
	int a[4][4];
	Matrix (){memset(a,0x3f,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
				for(int k=0;k<4;k++)
					c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
		return c;
	}
}g[N];
struct SegmentTree{
	Matrix a[N<<2];
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void build(int p,int l,int r){
		if(l==r){a[p]=g[l];return;}
		build(ls,l,mid);build(rs,mid+1,r);
		a[p]=a[ls]*a[rs];
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return a[p];
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return query(ls,l,mid,L,R)*query(rs,mid+1,r,L,R);
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
int main(){
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	for(int i=1;i<=n;i++){
		g[i].a[0][0]=g[i].a[1][1]=g[i].a[2][2]=g[i].a[3][3]=0;
		cnt[i]=cnt[i-1];lst[i]=lst[i-1];
		switch(s[i]){
			case '2':g[i].a[0][0]=1;g[i].a[0][1]=0;break;
			case '0':g[i].a[1][1]=1;g[i].a[1][2]=0;break;
			case '1':g[i].a[2][2]=1;g[i].a[2][3]=0;break;
			case '6':g[i].a[3][3]=1;++cnt[i];break;
			case '7':lst[i]=i;break;
		}
	}
	seg.build(1,1,n);
	for(int i=1,l,r;i<=m;i++){
		scanf("%d%d",&l,&r);
		if(lst[r]<l){
			printf("-1\n");
			continue;
		}
		Matrix f;f.a[0][0]=0;
		f=f*seg.query(1,1,n,l,lst[r]);
		int ans=f.a[0][3]+cnt[r]-cnt[lst[r]];
		printf("%d\n",ans>1e9?-1:ans);
	}
	return 0;
}
点击查看H题代码
#include<bits/stdc++.h>
using namespace std;
const int N=6e4+5;
int k,n,m,q;
struct Matrix{
	int a[5][5];
	Matrix (){memset(a,0x3f,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<5;i++)
			for(int j=0;j<5;j++)
				for(int k=0;k<5;k++)
					c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
		return c;
	}
}g[N];
struct SegmentTree{
	Matrix a[N<<2];
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void build(int p,int l,int r){
		if(l==r){a[p]=g[l];return;}
		build(ls,l,mid);build(rs,mid+1,r);
		a[p]=a[ls]*a[rs];
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return a[p];
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return query(ls,l,mid,L,R)*query(rs,mid+1,r,L,R);
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
int main(){
	scanf("%d%d%d%d",&k,&n,&m,&q);
	for(int i=1,u,v,w;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		g[u/k+1].a[u%k][v%k]=w;
	}
	seg.build(1,1,n/k);
	for(int i=1,u,v;i<=q;i++){
		scanf("%d%d",&u,&v);
		if(v/k<=u/k){printf("-1\n");continue;}
		Matrix f;f.a[0][u%k]=0;
		f=f*seg.query(1,1,n/k,u/k+1,v/k);
		int ans=f.a[0][v%k];
		printf("%d\n",ans>1e9?-1:ans);
	}
	return 0;
}
点击查看I题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct Matrix{
	ll a[2][2];
	Matrix (){memset(a,0x3f,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				for(int k=0;k<2;k++)
					c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
		return c;
	}
};
int n,m,k,fa[N][20],dep[N];Matrix f[N][20],g[N][20];
int head[N],ver[N<<1],nxt[N<<1],tot=1;Matrix val[N<<1];
void add(int u,int v,Matrix w){
	ver[++tot]=v;val[tot]=w;
	nxt[tot]=head[u];head[u]=tot;
}
void dfs(int u){
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u][0]){
			fa[v][0]=u;
			f[v][0]=val[i^1];g[v][0]=val[i];
			dep[v]=dep[u]+1;
			dfs(v);
		}
}
void pre(){
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i<=n;i++)if(fa[i][j-1]){
			fa[i][j]=fa[fa[i][j-1]][j-1];
			f[i][j]=f[i][j-1]*f[fa[i][j-1]][j-1];
			g[i][j]=g[fa[i][j-1]][j-1]*g[i][j-1];
		}
}
int LCA(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	int d=dep[u]-dep[v];
	for(int i=18;i>=0;i--)
		if(d&(1<<i))u=fa[u][i];
	if(u==v)return u;
	for(int i=18;i>=0;i--)
		if(fa[u][i]!=fa[v][i])
			u=fa[u][i],v=fa[v][i];
	return fa[u][0];
}
int st[50][2],top;
int main(){
	scanf("%d%d%d",&n,&k,&m);
	for(int i=1,u,v,a,b,t;i<n;i++){
		scanf("%d%d%d%d%d",&u,&v,&a,&b,&t);
		Matrix w;t=2*t-1;
		w.a[0][0]=w.a[1][0]=a;
		w.a[0][1]=k+a+t*b;w.a[1][1]=a+t*b;add(v,u,w);
		w.a[0][1]=k+a-t*b;w.a[1][1]=a-t*b;add(u,v,w);
	}
	dfs(1);pre();
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		int t=dep[LCA(u,v)];
		Matrix ans;ans.a[0][0]=0;
		int s=dep[u]-t;
		for(int j=18;j>=0;j--)
			if(s&(1<<j))ans=ans*f[u][j],u=fa[u][j];
		s=dep[v]-t;top=0;
		for(int j=18;j>=0;j--)
			if(s&(1<<j))st[++top][0]=v,st[top][1]=j,v=fa[v][j];
		while(top)ans=ans*g[st[top][0]][st[top][1]],--top;
		printf("%lld\n",min(ans.a[0][0],ans.a[0][1]));
	}
	return 0;
}
点击查看J题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,INF=1e9;
int n,m,a[N],f[N][2];
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
int fa[N],top[N],L[N],dfn,R[N],siz[N],son[N],id[N];
struct Matrix{
	int a[2][2];
	Matrix (){memset(a,0,sizeof(a));}
	Matrix operator *(const Matrix &b)const{
		Matrix c;
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				for(int k=0;k<2;k++)
					c.a[i][j]=max(c.a[i][j],a[i][k]+b.a[k][j]);
		return c;
	}
}g[N];
struct SegmentTree{
	Matrix a[N<<2];
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void build(int p,int l,int r){
		if(l==r){a[p]=g[id[l]];return;}
		build(ls,l,mid);
		build(rs,mid+1,r);
		a[p]=a[ls]*a[rs];
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return a[p];
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return query(ls,l,mid,L,R)*query(rs,mid+1,r,L,R);
	}
	void modify(int p,int l,int r,int x){
		if(l==r){a[p]=g[id[l]];return;}
		if(x<=mid)modify(ls,l,mid,x);
		else modify(rs,mid+1,r,x);
		a[p]=a[ls]*a[rs];
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
void dfs(int u){
	f[u][1]=a[u];siz[u]=1;
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]){
			fa[v]=u;
			dfs(v);siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
			f[u][0]+=max(f[v][0],f[v][1]);
			f[u][1]+=f[v][0];
		}
}
void rdfs(int u,int tp){
	g[u].a[1][0]=a[u];g[u].a[1][1]=-INF;
	L[u]=R[u]=++dfn;R[tp]=dfn;id[dfn]=u;top[u]=tp;
	if(son[u])rdfs(son[u],tp);
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]&&v!=son[u]){
			rdfs(v,v);
			g[u].a[0][0]+=max(f[v][0],f[v][1]);
			g[u].a[1][0]+=f[v][0];
		}
	g[u].a[0][1]=g[u].a[0][0];
}
void update(int u,int val){
	g[u].a[1][0]+=val-a[u];a[u]=val;
	while(u){
		Matrix lst=seg.query(1,1,n,L[top[u]],R[top[u]]);
		seg.modify(1,1,n,L[u]);
		Matrix now=seg.query(1,1,n,L[top[u]],R[top[u]]);
		u=fa[top[u]];
		g[u].a[0][0]+=max(now.a[0][0],now.a[1][0])-max(lst.a[0][0],lst.a[1][0]);
		g[u].a[1][0]+=now.a[0][0]-lst.a[0][0];
		g[u].a[0][1]=g[u].a[0][0];
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",a+i);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1);rdfs(1,1);seg.build(1,1,n);
	for(int i=1,u,val;i<=m;i++){
		scanf("%d%d",&u,&val);
		update(u,val);
		Matrix ans=seg.query(1,1,n,1,R[1]);
		printf("%d\n",max(ans.a[0][0],ans.a[1][0]));
	}
	return 0;
}
点击查看K题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,INF=1e9+7;
int n,m;ll a[N],f[N];char op;
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
struct Matrix{
	ll a[2][2];
	Matrix (){memset(a,0x3f,sizeof(a));}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				for(int k=0;k<2;k++)
					c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
		return c;
	}
}g[N];
int fa[N],siz[N],top[N],L[N],dfn,R[N],son[N],id[N];
void dfs(int u){
	siz[u]=1;
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]){
			fa[v]=u;dfs(v);siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
			f[u]+=min(f[v],a[v]);
		}
	if(!nxt[head[u]])f[u]=INF;
}
void rdfs(int u,int tp){
	g[u].a[0][1]=a[u];g[u].a[0][0]=g[u].a[1][1]=0;
	L[u]=++dfn;id[dfn]=u;R[tp]=dfn;top[u]=tp;
	if(son[u])rdfs(son[u],tp);
	else g[u].a[0][0]=INF;
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]&&v!=son[u]){
			rdfs(v,v);
			g[u].a[0][0]+=min(f[v],a[v]);
		}
}
struct SegmentTree{
	Matrix a[N<<2];
	#define ls p<<1
	#define rs p<<1|1
	#define mid (l+r>>1)
	void build(int p,int l,int r){
		if(l==r){a[p]=g[id[l]];return;}
		build(ls,l,mid);
		build(rs,mid+1,r);
		a[p]=a[ls]*a[rs];
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return a[p];
		if(R<=mid)return query(ls,l,mid,L,R);
		if(L>mid)return query(rs,mid+1,r,L,R);
		return query(ls,l,mid,L,R)*query(rs,mid+1,r,L,R);
	}
	void modify(int p,int l,int r,int x){
		if(l==r){a[p]=g[id[l]];return;}
		if(x<=mid)modify(ls,l,mid,x);
		else modify(rs,mid+1,r,x);
		a[p]=a[ls]*a[rs];
	}
	#undef ls
	#undef rs
	#undef mid
}seg;
void update(int u,int val){
	g[u].a[0][1]+=val;a[u]+=val;
	while(u){
		Matrix lst=seg.query(1,1,n,L[top[u]],R[top[u]]);
		seg.modify(1,1,n,L[u]);
		Matrix now=seg.query(1,1,n,L[top[u]],R[top[u]]);
		u=fa[top[u]];
		g[u].a[0][0]+=min(now.a[0][0],now.a[0][1])-min(lst.a[0][0],lst.a[0][1]);
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld",a+i);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1);rdfs(1,1);seg.build(1,1,n);
	scanf("%d",&m);
	for(int i=1,u,val;i<=n;i++){
		while(op=getchar(),op!='Q'&&op!='C');
		scanf("%d",&u);
		if(op=='Q'){
			Matrix ans=seg.query(1,1,n,L[u],R[top[u]]);
			printf("%lld\n",min(ans.a[0][0],ans.a[0][1]));
		}
		else{scanf("%d",&val);update(u,val);}
	}
	return 0;
}

点击查看L题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;const ll INF=1e18;
int n,m,p[N];ll f[N][2];char type[5];
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
struct Matrix{
	ll a[2][2];
	Matrix (){a[0][0]=a[0][1]=a[1][0]=a[1][1]=INF;}
	Matrix operator *(const Matrix&b)const{
		Matrix c;
		c.a[0][0]=min(a[0][0]+b.a[0][0],a[0][1]+b.a[1][0]);
		c.a[1][0]=min(a[1][0]+b.a[0][0],a[1][1]+b.a[1][0]);
		c.a[0][1]=min(a[0][0]+b.a[0][1],a[0][1]+b.a[1][1]);
		c.a[1][1]=min(a[1][0]+b.a[0][1],a[1][1]+b.a[1][1]);
		return c;
	}
}g[N];
int fa[N],top[N],siz[N],L[N],dfn,R[N],son[N],id[N];
void dfs(int u){
	f[u][1]=p[u];siz[u]=1;
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]){
			fa[v]=u;dfs(v);siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
			f[u][0]+=f[v][1];
			f[u][1]+=min(f[v][0],f[v][1]);
		}
}
void rdfs(int u,int tp){
	g[u].a[0][0]=p[u];g[u].a[1][0]=0;
	L[u]=++dfn;id[dfn]=u;top[u]=tp;R[tp]=dfn;
	if(son[u])rdfs(son[u],tp);
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa[u]&&v!=son[u]){
			rdfs(v,v);
			g[u].a[0][0]+=min(f[v][0],f[v][1]);
			g[u].a[1][0]+=f[v][1];
		}
	g[u].a[0][1]=g[u].a[0][0];
}
struct SegmentTree{
	Matrix a[N<<2];
	#define mid (l+r>>1)
	void build(int p,int l,int r){
		if(l==r){a[p]=g[id[l]];return;}
		build(p<<1,l,mid);
		build(p<<1|1,mid+1,r);
		a[p]=a[p<<1]*a[p<<1|1];
	}
	void modify(int p,int l,int r,int x){
		if(l==r){a[p]=g[id[l]];return;}
		if(x<=mid)modify(p<<1,l,mid,x);
		else modify(p<<1|1,mid+1,r,x);
		a[p]=a[p<<1]*a[p<<1|1];
	}
	Matrix query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return a[p];
		if(R<=mid)return query(p<<1,l,mid,L,R);
		if(L>mid)return query(p<<1|1,mid+1,r,L,R);
		return query(p<<1,l,mid,L,R)*query(p<<1|1,mid+1,r,L,R);
	}
	#undef mid
}seg;
void update(int u,int op,Matrix c){
	if(op==1)g[u].a[1][0]=INF;
	else if(op==2)g[u]=c;
	else g[u].a[0][0]=g[u].a[0][1]=INF;
	while(u){
		Matrix lst=seg.query(1,1,n,L[top[u]],R[top[u]]);
		seg.modify(1,1,n,L[u]);
		Matrix now=seg.query(1,1,n,L[top[u]],R[top[u]]);
		u=fa[top[u]];
		g[u].a[0][0]+=min(now.a[0][0],now.a[1][0])-min(lst.a[0][0],lst.a[1][0]);
		g[u].a[1][0]+=now.a[0][0]-lst.a[0][0];g[u].a[0][1]=g[u].a[0][0];
	}
}
int main(){
//	freopen("defense.in","r",stdin);
//	freopen("defense.out","w",stdout);
	scanf("%d%d",&n,&m);scanf("%s",type);
	for(int i=1;i<=n;i++)scanf("%d",p+i);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1);rdfs(1,1);seg.build(1,1,n);
	for(int i=1,a,x,b,y;i<=m;i++){
		scanf("%d%d%d%d",&a,&x,&b,&y);
		Matrix tmpa=g[a];update(a,x,tmpa);
		Matrix tmpb=g[b];update(b,y,tmpb);
		Matrix ans=seg.query(1,1,n,1,R[1]);
		ll res=min(ans.a[0][0],ans.a[1][0]);
		printf("%lld\n",res>1e15?-1:res);
		update(b,2,tmpb);update(a,2,tmpa);
	}
	return 0;
}
posted @ 2023-06-02 19:58  by_chance  阅读(37)  评论(0编辑  收藏  举报