【线段树维护矩阵向量】LibreOJ - 2980 大魔法师

题链

线段树维护矩阵模板题

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
#define LL long long
#define ll long long
#define ULL unsigned long long
#define Pair pair<LL,LL>
#define ls rt<<1
#define rs rt<<1|1
#define Pi acos(-1.0)
#define eps 1e-6
#define DBINF 1e100
#define mod 998244353 
#define MAXN 1e18
#define MS 250009

int n,m;
struct matrix{
	LL rown,coln,a[5][5];	
}p[MS<<2];
matrix la[MS<<2],I;
bool isla[MS<<2];

matrix operator + (matrix t1,matrix t2){
	matrix t = {t1.rown,t1.coln};
	memset(t.a,0,sizeof t.a);
	for(int i=1;i<=t.rown;i++){
		for(int j=1;j<=t.coln;j++){
			t.a[i][j] = t1.a[i][j] + t2.a[i][j];
			t.a[i][j] %= mod;
		}
	}
	return t;
}

matrix operator * (matrix t1,matrix t2){
	matrix t = {t1.rown,t2.coln};
	memset(t.a,0,sizeof t.a);
	for(int u=1;u<=t.rown;u++){
		for(int v=1;v<=t.coln;v++){
			for(int i=1;i<=t1.coln;i++){
				t.a[u][v] += t1.a[u][i]*t2.a[i][v];
				t.a[u][v] %= mod;
			}
		}
	}
	return t;
}

void push_up(int rt){
	p[rt] = p[ls] + p[rs];
}

void build(int l,int r,int rt){
	la[rt] = I;
	if(l == r){
		LL a,b,c;
		cin >> a >> b >> c;
		p[rt] = {1,4};
		p[rt].a[1][1] = a;
		p[rt].a[1][2] = b;
		p[rt].a[1][3] = c;
		p[rt].a[1][4] = 1;
		return;
	}
	int m = l+r>>1;
	build(l,m,ls);
	build(m+1,r,rs);
	push_up(rt);
}

void update(int rt,matrix f){
	p[rt] = p[rt] * f;
	la[rt] = la[rt] * f;
	isla[rt] = 1;
}

void push_down(int rt){
	if(isla[rt]){
		update(ls,la[rt]);
		update(rs,la[rt]);
		la[rt] = I;
		isla[rt] = 0;
	}
}

void modify(int L,int R,int l,int r,int rt,matrix f){
	if(L <= l && r <= R){
		update(rt,f);
		return;
	}
	int m = l+r>>1;
	push_down(rt);
	if(m >= L) modify(L,R,l,m,ls,f);
	if(m <  R) modify(L,R,m+1,r,rs,f);
	push_up(rt);
}

matrix query(int L,int R,int l,int r,int rt){
	if(L <= l && r <= R){
		return p[rt];
	}
	int m = l+r>>1;
	push_down(rt);
	if(m < L) return query(L,R,m+1,r,rs);
	else if(m >= R) return query(L,R,l,m,ls);
	else return query(L,R,l,m,ls) + query(L,R,m+1,r,rs);
}

void init(){
	I = {4,4};
	for(int i=1;i<=4;i++) I.a[i][i] = 1;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	init(); build(1,n,1);
	cin >> m;
	matrix f = {4,4};
	for(int i=1;i<=m;i++){
		LL op,l,r,val;
		cin >> op >> l >> r;
		memset(f.a,0,sizeof f.a);
		if(op == 1){
			f.a[1][1] = f.a[2][1] = f.a[2][2] = f.a[3][3] = f.a[4][4] = 1;
		}
		else if(op == 2){
			f.a[1][1] = f.a[2][2] = f.a[3][2] = f.a[3][3] = f.a[4][4] = 1;
		}
		else if(op == 3){
			f.a[1][1] = f.a[2][2] = f.a[1][3] = f.a[3][3] = f.a[4][4] = 1;
		}
		else if(op == 4){
			f.a[1][1] = f.a[2][2] = f.a[3][3] = f.a[4][4] = 1;
			cin >> f.a[4][1];
		}
		else if(op == 5){
			f.a[1][1] = f.a[3][3] = f.a[4][4] = 1;
			cin >> f.a[2][2];
		}
		else if(op == 6){
			f.a[1][1] = f.a[2][2] = f.a[4][4] = 1;
			cin >> f.a[4][3];
		}
		if(op != 7) modify(l,r,1,n,1,f);
		else{
			matrix ans = query(l,r,1,n,1);
			cout << ans.a[1][1] << " ";
			cout << ans.a[1][2] << " ";
			cout << ans.a[1][3] << "\n";
		}
	}
	
	
	return 0;
}
posted @ 2021-07-24 20:06  棉被sunlie  阅读(60)  评论(0)    收藏  举报