习题:大魔法师(矩阵&线段树&卡常)

题目

传送门

思路

一道十分恶心的卡常毒瘤题目

关键是将操作转换成为一个矩阵的形式,

再用线段树来维护

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int mod=998244353;
void read(int &x)
{
	x=0;
	int f=1;
	char c=getchar();
	while('0'>c||c>'9')
	{
		if(c=='-')
			f=-1;
		c=getchar();
	}
	while('0'<=c&&c<='9')
	{
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
	x*=f;
}
void write(int x)
{
	if(x>9)
		write(x/10);
	putchar(x%10+'0');
}
struct matrix
{
	int n,m;
	int a[5][5];
	matrix()
	{
		n=0;
		m=0;
		for(int i=1;i<=4;i++)
			for(int j=1;j<=4;j++)
				a[i][j]=0;
	}
	matrix operator * (const matrix &b)
	{
		matrix c;
		c.n=n;
		c.m=b.m;
		for(int i=1;i<=n;i++)
		{
			for(int k=1;k<=m;k++)
			{
				if(!a[i][k])
					continue;
				for(int j=1;j<=b.m;j++)
				{
					int t=1ll*a[i][k]*b.a[k][j]%mod;
					c.a[i][j]+=t;
					c.a[i][j]=c.a[i][j]>=mod?c.a[i][j]-mod:c.a[i][j];
				}
			}
		}
		return c;
	} 
	matrix operator + (const matrix &b)
	{
		matrix c;
		c.n=n;
		c.m=m;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				c.a[i][j]=a[i][j]+b.a[i][j];
				c.a[i][j]=c.a[i][j]>=mod?c.a[i][j]-mod:c.a[i][j];
			}
		return c;
	}
};
struct tree
{
	int l;
	int r;
	matrix w;
	matrix lazy;
}tre[600005];
matrix meta;
matrix vec_meta;
matrix t;
matrix opt[8];
int n,m;
int optt,l,r,v;
void init()
{
	t.n=4;
	t.m=1;
	vec_meta.n=4;
	vec_meta.m=1;
	meta.n=4;
	meta.m=4;
	for(int i=1;i<=4;i++)
		meta.a[i][i]=1;
	opt[1]=meta;
	opt[1].a[1][2]=1;
	opt[2]=meta;
	opt[2].a[2][3]=1;
	opt[3]=meta;
	opt[3].a[3][1]=1;
	opt[4]=meta;
	opt[5]=meta;
	opt[6]=meta;
}
void build(int k,int l=1,int r=n)
{
	tre[k].l=l;
	tre[k].r=r;
	tre[k].lazy=meta;
	tre[k].w.n=4;
	tre[k].w.m=1;
	if(l==r)
	{
		for(int i=1;i<=3;i++)
			read(tre[k].w.a[i][1]);
		tre[k].w.a[4][1]=1;
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	tre[k].w=tre[k<<1].w+tre[k<<1|1].w;
}
void push_down(int k)
{
	if(tre[k].l==tre[k].r)
		return;
	tre[k<<1].lazy=tre[k].lazy*tre[k<<1].lazy;
	tre[k<<1|1].lazy=tre[k].lazy*tre[k<<1|1].lazy;
	tre[k<<1].w=tre[k].lazy*tre[k<<1].w;
	tre[k<<1|1].w=tre[k].lazy*tre[k<<1|1].w;
	tre[k].lazy=meta;
}
void change(int k)
{
	if(tre[k].l>r||l>tre[k].r)
		return;
	if(l<=tre[k].l&&tre[k].r<=r)
	{
		tre[k].w=opt[optt]*tre[k].w;
		tre[k].lazy=opt[optt]*tre[k].lazy;
		return;
	}
	push_down(k);
	change(k<<1);
	change(k<<1|1);
	tre[k].w=tre[k<<1].w+tre[k<<1|1].w;
}
void ask(int k)
{
	if(tre[k].l>r||l>tre[k].r)
		return;
	if(l<=tre[k].l&&tre[k].r<=r)
	{
		t=t+tre[k].w;
		return;
	}
	push_down(k);
	ask(k<<1);
	ask(k<<1|1);
}
int main()
{
	init();
	read(n);
	build(1);
	read(m);
	for(int i=1;i<=m;i++)
	{
		read(optt);
		read(l);
		read(r);
		if(optt==7)
		{
			for(int i=1;i<=4;i++)
				for(int j=1;j<=1;j++)
					t.a[i][j]=0;
			ask(1);
			write(t.a[1][1]);
			putchar(' ');
			write(t.a[2][1]);
			putchar(' ');
			write(t.a[3][1]);
			putchar('\n');
			continue;
		}
		if(optt==4)
		{
			read(v);
			opt[4].a[1][4]=v;
		}
		if(optt==5)
		{
			read(v);
			opt[5].a[2][2]=v;
		}
		if(optt==6)
		{
			read(v);
			opt[6].a[3][3]=0;
			opt[6].a[3][4]=v;
		}
		change(1);
	}
	return 0;
}
posted @ 2020-01-04 17:04  loney_s  阅读(163)  评论(0)    收藏  举报