• 大魔*


    前言

    此题属于周末 狂欢 自闭赛系列

    题目

    LOJ

    USOJ(蒟蒻专用)

    讲解

    首先这明显是一道数据结构题:线段树

    但是我们怎么维护呢?我们有整整六个操作!!!而且操作彼此之间还有顺序问题,这导致我们的懒标记并不好搞

    我们 自己想 通过老师的讲解:使用矩阵!!!

    这样所有的问题都迎刃而解了

    线段树的每个节点使用(1 imes 4)的矩阵,(4 imes 4)的懒标记

    转移很好想

    想不出来看代码

    另外,这道题 轻微 卡常

    代码

    //12252024832524
    #pragma GCC optimize(2)
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 250005;
    const int MOD = 998244353;
    int n;
    
    int Read()
    {
    	int x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    void Put1(int x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    void Put(int x)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x);
    }
    template <typename T>T Max(T x,T y){return x > y ? x : y;}
    template <typename T>T Min(T x,T y){return x < y ? x : y;}
    template <typename T>T Abs(T x){return x < 0 ? -x : x;}
    
    int Add(int x)
    {
    	if(x >= MOD) return x - MOD;
    	return x;
    }
    
    struct Matrix
    {
    	int n,m,a[5][5];
    	
    	Matrix(){for(int i = 1;i <= 4;++ i) for(int j = 1;j <= 4;++ j) a[i][j] = 0;}
    	
    	void put()
    	{
    		for(register int i = 1;i <= n;++ i)
    		{
    			for(register int j = 1;j < m;++ j)
    			{
    				Put(a[i][j]);
    				putchar(' ');
    			}
    			Put(a[i][m]);
    			putchar('
    ');
    		}
    	}
    	
    	Matrix operator + (const Matrix &C)//临时加法 
    	{
    		Matrix r;
    		r.n = n;
    		r.m = m;
    		for(register int j = 1;j <= m;++ j)
    			r.a[1][j] = Add(a[1][j] + C.a[1][j]);
    		return r;
    	}
    	
    	Matrix operator * (const Matrix &C)
    	{
    		Matrix r;
    		r.n = n;
    		r.m = C.m;
    		for(register int i = 1;i <= r.n;++ i)
    			for(register int k = 1;k <= m;++ k)
    			    if(a[i][k])
    			        for(register int j = 1;j <= r.m;++ j)
    					    r.a[i][j] = Add(1ll * a[i][k] * C.a[k][j] % MOD + r.a[i][j]);
    		return r;
    	}
    }im,optm[7],nt;//单位矩阵,操作的矩阵,空矩阵 
    
    struct SegmentTree
    {
    	struct node
    	{
    		int l,r;
    		Matrix mat,lazy;
    	}a[950019];
    	
    	void up(const int x)
    	{
    		a[x].mat = a[x<<1].mat + a[x<<1|1].mat;
    	}
    	
    	void down(const int x)
    	{
    		a[x<<1].mat = a[x<<1].mat * a[x].lazy;
    		a[x<<1|1].mat = a[x<<1|1].mat * a[x].lazy;
    		a[x<<1].lazy = a[x<<1].lazy * a[x].lazy;
    		a[x<<1|1].lazy = a[x<<1|1].lazy * a[x].lazy;
    		a[x].lazy = im;
    	}
    	
    	void build(const int x,const int l,const int r)
    	{
    		a[x].l = l;
    		a[x].r = r;
    		a[x].mat.n = 1;
    		a[x].mat.m = 4;
    		a[x].mat.a[1][4] = r-l+1;
    		a[x].lazy = im;
    		if(l == r)
    		{
    			a[x].mat.a[1][1] = Read();//Ai
    			a[x].mat.a[1][2] = Read();//Bi
    			a[x].mat.a[1][3] = Read();//Ci
    			return ;
    		}
    		int mid = (l+r) >> 1;
    		build(x<<1,l,mid);
    		build(x<<1|1,mid+1,r);
    		up(x);
    	}
    	
    	void update(const int x,const int l,const int r,Matrix val)
    	{
    		if(a[x].l > r || a[x].r < l) return;
    		if(l <= a[x].l && a[x].r <= r)
    		{
    			a[x].mat = a[x].mat * val;
    			a[x].lazy = a[x].lazy * val;
    			return ;
    		}
    		down(x);
    		update(x<<1,l,r,val);
    		update(x<<1|1,l,r,val);
    		up(x);
    	}
    	
    	Matrix query(const int x,const int l,const int r)
    	{
    		if(a[x].l > r || a[x].r < l) return nt;
    		if(l <= a[x].l && a[x].r <= r) return a[x].mat;
    		down(x);
    		return query(x<<1,l,r) + query(x<<1|1,l,r);
    	}
    	
    }t;
    
    void pre()
    {
    	im.n = im.m = nt.m = 4;
    	nt.n = 1;
    	for(register int i = 1;i <= 4;++ i) im.a[i][i] = 1;
    	for(register int i = 1;i <= 6;++ i) optm[i] = im;
    	optm[1].a[2][1] = 1;//1. Ai += Bi
    	optm[2].a[3][2] = 1;//2. Bi += Ci
    	optm[3].a[1][3] = 1;//3. Ci += Ai
    	optm[6].a[3][3] = 0;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	pre();
    	n = Read();
    	t.build(1,1,n);
    	for(register int Q = Read(); Q ;-- Q)
    	{
    		int opt = Read(),l = Read(),r = Read();
    		if(opt <= 3) t.update(1,l,r,optm[opt]);
    		else if(opt <= 6)
    		{
    			int v = Read();
    			if(opt == 4) optm[4].a[4][1] = v;//4. Ai += v
    			else if(opt == 5) optm[5].a[2][2] = v;//5. Bi *= v
    			else optm[6].a[4][3] = v;//6. Ci = v
    			t.update(1,l,r,optm[opt]);
    		}
    		else
    		{
    			Matrix val = t.query(1,l,r);
    			val.m = 3;
    			val.put();
    		}
    	}
    	return 0;
    }
    

    卡常卡吐了

    我以后码矩阵一定从(sout0)开始

  • 相关阅读:
    导出表结构语句
    closeChannel: close the connection to remote address[] result: true
    spingboot使用rabbitmq
    服务器很卡问题排查
    docker-compose安装nginx
    Docker方式安装ShowDoc
    "docker build" requires exactly 1 argument
    Intellij IDEA常用快捷键介绍 Intellij IDEA快捷键大全汇总
    IDEA 2018 3.4 激活破解方法
    jpress:v3.2.5的docker-compose安装
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13395253.html
Copyright © 2020-2023  润新知