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;
}