[THUSCH 2017]大魔法师

大魔法师

题解

有一道线段树水题。

好吧,看到每一个操作,惊奇地发现这几个操作矩阵都可以解决,而题目又要求更改一个区间,所以用线段树来维护。

我们可以将树上的每一个点建成一个1*4的矩阵,第一二三个点分别记录a,b,c的值,而第四个记录区间的大小。合并时将两个子区间相加即可。

进行更改时的矩阵构造也很简单,前面的相加很好想,分别是\begin{Bmatrix} 1 & 0& 0& 0\\ 1 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{Bmatrix} \begin{Bmatrix} 1 & 0& 0& 0\\ 0 & 1 & 0 & 0\\ 0 & 1 & 1 & 0\\ 0 & 0 & 0 & 1 \end{Bmatrix} \begin{Bmatrix} 1 & 0& 1& 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{Bmatrix}

而后面的与v有关的几个操作也很明显,分别为\begin{Bmatrix} 1 & 0& 0& 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ v & 0 & 0 & 1 \end{Bmatrix} \begin{Bmatrix} 1 & 0& 0& 0\\ 0 & v & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{Bmatrix} \begin{Bmatrix} 1 & 0& 0& 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & v & 1 \end{Bmatrix}

之后加个懒标记就可以了,具体操作也很简单。

源码

%: pragma GCC optimize(3)
//%: pragma GCC optimize(2)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
#define MAXN 250000
typedef long long LL;
const int mo=998244353;
#define gc() getchar()
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
}
inline int add(int a,int b){return a+b>mo?a+b-mo:a+b;}
struct ming{
	int c[5][5],n,m;
	ming(){n=m=0;memset(c,0,sizeof(c));}
	ming operator * (const ming& b){
		ming r;r.n=n;r.m=b.m;
		for(int i=1;i<=r.n;++i)
			for(int j=1;j<=m;++j)
				if(c[i][j])
					for(int k=1;k<=r.m;++k)
						r.c[i][k]=add(r.c[i][k],1ll*c[i][j]*b.c[j][k]%mo);
		return r;
	}
	ming operator + (const ming& b){
		ming r;r.n=n;r.m=m;
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				r.c[i][j]=add(c[i][j],b.c[i][j]);
		return r;
	}
	void clear(){memset(c,0,sizeof(c));n=m=0;}
	void init(){n=m=4;for(int i=1;i<=n;++i)c[i][i]=1;}
	bool empty(){
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j){
				if(i==j&&c[i][j]!=1)return false;
				if(i!=j&&c[i][j]!=0)return false;
			}
		return true;
	}
}B[MAXN<<2],lzy[MAXN<<2];
int n,m,a[MAXN],b[MAXN],c[MAXN];
void build(int rt,int l,int r){
	if(l>r)return ;
	if(l==r){
		B[rt].n=1;B[rt].m=4;
		B[rt].c[1][1]=a[l];
		B[rt].c[1][2]=b[l];
		B[rt].c[1][3]=c[l];
		B[rt].c[1][4]=1;
		lzy[rt].init();
		//printf("build%d %d %d\n",rt,l,r);B[rt].print();
		//puts("\n\n");
		return ;
	}
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	B[rt]=B[rt<<1]+B[rt<<1|1];lzy[rt].init();
	//printf("build%d %d %d\n",rt,l,r);B[rt].print();
	//puts("\n\n");
}
void pushdown(int rt){
	if(lzy[rt].empty())return ;
	B[rt<<1]=B[rt<<1]*lzy[rt];
	B[rt<<1|1]=B[rt<<1|1]*lzy[rt];
	lzy[rt<<1]=lzy[rt<<1]*lzy[rt];
	lzy[rt<<1|1]=lzy[rt<<1|1]*lzy[rt];
	lzy[rt].clear();lzy[rt].init();
}
void insert(int rt,int l,int r,int al,int ar,ming aw){
	if(l>r||l>ar||r<al)return ;
	//printf("%d %d %d %d\n",l,r,al,ar);
	if(al<=l&&r<=ar){
		//B[rt].print();
		B[rt]=B[rt]*aw;lzy[rt]=lzy[rt]*aw;
		//printf("insert%d %d %d\n",rt,l,r);B[rt].print();
		//puts("\n\n");
		return ;
	}
	int mid=l+r>>1;pushdown(rt);
	insert(rt<<1,l,mid,al,ar,aw);
	insert(rt<<1|1,mid+1,r,al,ar,aw);
	B[rt]=B[rt<<1]+B[rt<<1|1];
	//printf("insert%d %d %d\n",rt,l,r);B[rt].print();
	//puts("\n\n");
}
ming query(int rt,int l,int r,int al,int ar){
	ming res;res.n=1;res.m=4;
	if(l>r||l>ar||r<al)return res;
	if(al<=l&&r<=ar)return B[rt];
	int mid=l+r>>1;pushdown(rt);
	res=query(rt<<1,l,mid,al,ar)+query(rt<<1|1,mid+1,r,al,ar);
	return res;
}
ming A1,A2,A3,A4,A5,A6;
signed main(){ 
//freopen("2.in","r",stdin);
//freopen("3.out","w",stdout);
	read(n);
	for(int i=1;i<=n;++i)read(a[i]),read(b[i]),read(c[i]);
	build(1,1,n);read(m);
	A1.init();A1.c[2][1]=1;
	A2.init();A2.c[3][2]=1;
	A3.init();A3.c[1][3]=1;
	A4.init();A5.init();
	A6.init();A6.c[3][3]=0;
	for(int i=1;i<=m;++i){
		int opt;read(opt);
		if(opt==1){
			int l,r;read(l);read(r);
			//printf("111a%d %d\n",l,r);
			insert(1,1,n,l,r,A1);
		}
		if(opt==2){
			int l,r;read(l);read(r);
			insert(1,1,n,l,r,A2);
		}
		if(opt==3){
			int l,r;read(l);read(r);
			insert(1,1,n,l,r,A3);
		}
		if(opt==4){
			int l,r,v;read(l);read(r);read(v);
			A4.c[4][1]=v;insert(1,1,n,l,r,A4);
		}
		if(opt==5){
			int l,r,v;read(l);read(r);read(v);
			A5.c[2][2]=v;insert(1,1,n,l,r,A5);
		}
		if(opt==6){
			int l,r,v;read(l);read(r);read(v);
			A6.c[4][3]=v;insert(1,1,n,l,r,A6);
		}
		if(opt==7){
			int l,r;read(l);read(r);
			ming C=query(1,1,n,l,r);
			printf("%d %d %d\n",C.c[1][1],C.c[1][2],C.c[1][3]);
		}
	}
    return 0;
}

谢谢!!!

发布了117 篇原创文章 · 获赞 154 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Tan_tan_tann/article/details/103832918
今日推荐