Description

大魔法师小 L 制作了 \(n\) 个魔力水晶球,每个水晶球有水、火、土三个属性的能量值。小 L 把这 \(n\) 个水晶球在地上从前向后排成一行,然后开始今天的魔法表演。

我们用 \(A_i,B_i,C_i\) 分别表示从前向后第 \(i\) 个水晶球(下标从 \(1\) 开始)的水、火、土的能量值。

小 L 计划施展 \(m\) 次魔法。每次,他会选择一个区间 \([l,r]\),然后施展以下 \(3\) 大类、\(7\) 种魔法之一:

1. 魔力激发:令区间里每个水晶球中特定属性的能量爆发,从而使另一个特定属性的能量增强。具体来说,有以下三种可能的表现形式:

  • 土元素激发火元素能量:令 \(A_i=A_i+B_i\)。
  • 水元素激发土元素能量:令 \(B_i=B_i+C_i\)。
  • 火元素激发水元素能量:令 \(C_i=C_i+A_i\)。

需要注意的是,增强一种属性的能量并不会改变另一种属性的能量,例如 \(A_i+B_i\) 并不会使 \(B_i\) 增加或减少。

2. 魔力增强:小 L 挥舞法杖,消耗自身 \(v\) 点法力值,来改变区间里每个水晶球的特定属性的能量。具体来说,有以下三种可能的表现形式:

  • 火元素能量定值增强:令 \(A_i=A_i+v\)。
  • 水元素能量翻倍增强:令 \(B_i=B_i\cdot v\)。
  • 土元素能量吸收融合:令 \(C_i=v\)。

3. 魔力释放:小 L 将区间里所有水晶球的能量聚集在一起,融合成一个新的水晶球,然后送给场外观众。生成的水晶球每种属性的能量值等于区间内所有水晶球对应能量值的代数和。需要注意的是,魔力释放的过程不会真正改变区间内水晶球的能量。

值得一提的是,小 L 制造和融合的水晶球的原材料都是定制版的 OI 工厂水晶,所以这些水晶球有一个能量阈值 \(998244353\)。当水晶球中某种属性的能量值大于等于这个阈值时,能量值会自动对阈值取模,从而避免水晶球爆炸。

小 W 为小 L(唯一的)观众,围观了整个表演,并且收到了小 L 在表演中融合的每个水晶球。小 W 想知道,这些水晶球蕴涵的三种属性的能量值分别是多少。

题目大意

给定一个长度为 \(n\) 的序列,每个位置有 \(A_i,B_i,C_i\) 三种权值。

有 \(m\) 次操作,分别可能是区间 \(A_i=A_i+B_i\)、\(B_i=B_i+C_i\)、\(C_i=C_i+A_i\)、\(A_i=A_i+v\)、\(B_i=B_i\cdot v\)、\(C_i=v\)。其中 \(v\) 是每次给定的常数。也可能是询问区间 \(A_i,B_i,C_i\) 分别的和。答案对 \(998244353\) 取模。\(n,m\leq 2.5\times 10^5\)。

Solution

考虑用矩阵维护这些操作。

操作一 \(A_i=A_i+B_i\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&0&0\\1&1&0&0\\0&0&1&0\\0&0&0&1\end{bmatrix}=\begin{bmatrix}A+B&B&C&1\end{bmatrix}\)

操作二 \(B_i=B_i+C_i\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&0&0\\0&1&0&0\\0&1&1&0\\0&0&0&1\end{bmatrix}=\begin{bmatrix}A&B+C&C&1\end{bmatrix}\)

操作三 \(C_i=C_i+A_i\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&1&0\\0&1&0&0\\0&0&1&0\\0&0&0&1\end{bmatrix}=\begin{bmatrix}A&B&C+A&1\end{bmatrix}\)

操作四 \(A_i=A_i+v\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&0&0\\0&1&0&0\\0&0&1&0\\v&0&0&1\end{bmatrix}=\begin{bmatrix}A+v&B&C&1\end{bmatrix}\)

操作五 \(B_i=B_i\cdot v\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&0&0\\0&v&0&0\\0&0&1&0\\0&0&0&1\end{bmatrix}=\begin{bmatrix}A&B\cdot v&C&1\end{bmatrix}\)

操作六 \(C_i=v\) 的转移:

\(\begin{bmatrix}A&B&C&1\end{bmatrix}\times \begin{bmatrix}1&0&0&0\\0&1&0&0\\0&0&0&0\\0&0&v&1\end{bmatrix}=\begin{bmatrix}A&B&v&1\end{bmatrix}\)

由于矩阵的结合律和分配律成立,单点修改可以自然地推广到区间,即推出矩阵后直接用线段树维护区间矩阵乘积即可。

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,mod=998244353;
int n,q,opt,l,r,v,ans[4];
struct data{
int a[4][4];
}f,sum[N<<2],tag[N<<2];
void mul(data &x,data &y){ //矩阵乘法
int c[4][4];
memset(c,0,sizeof(c));
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
c[i][j]=(c[i][j]+1ll*x.a[i][k]*y.a[k][j])%mod;
memcpy(x.a,c,sizeof(c));
}
void pushup(int p){
for(int i=0;i<4;i++)
sum[p].a[0][i]=(sum[p<<1].a[0][i]+sum[p<<1|1].a[0][i])%mod;
}
void pushdown(int p){
bool flag=1;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(tag[p].a[i][j]!=f.a[i][j]) flag=0; //非单位矩阵,则 flag=0
if(flag) return ;
mul(sum[p<<1],tag[p]),mul(tag[p<<1],tag[p]);
mul(sum[p<<1|1],tag[p]),mul(tag[p<<1|1],tag[p]);
tag[p]=f;
}
void build(int p,int l,int r){
sum[p].a[0][3]=r-l+1,tag[p]=f;
if(l==r){for(int i=0;i<3;i++) scanf("%d",&sum[p].a[0][i]);return ;}
int mid=(l+r)/2;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
void modify(int p,int l,int r,int lx,int rx,data v){
if(l>=lx&&r<=rx){mul(sum[p],v),mul(tag[p],v);return ;}
int mid=(l+r)/2;
pushdown(p);
if(lx<=mid) modify(p<<1,l,mid,lx,rx,v);
if(rx>mid) modify(p<<1|1,mid+1,r,lx,rx,v);
pushup(p);
}
void query(int p,int l,int r,int lx,int rx){
if(l>=lx&&r<=rx){
for(int i=0;i<3;i++)
ans[i]=(ans[i]+sum[p].a[0][i])%mod;
return ;
}
int mid=(l+r)/2;
pushdown(p);
if(lx<=mid) query(p<<1,l,mid,lx,rx);
if(rx>mid) query(p<<1|1,mid+1,r,lx,rx);
pushup(p);
}
signed main(){
for(int i=0;i<4;i++) f.a[i][i]=1; //单位矩阵
scanf("%d",&n),build(1,1,n),scanf("%d",&q);
while(q--){
scanf("%d%d%d",&opt,&l,&r);
if(opt<=6){
data tmp=f;
if(opt==1) tmp.a[1][0]=1;
else if(opt==2) tmp.a[2][1]=1;
else if(opt==3) tmp.a[0][2]=1;
else if(opt==4) scanf("%d",&v),tmp.a[3][0]=v;
else if(opt==5) scanf("%d",&v),tmp.a[1][1]=v;
else scanf("%d",&v),tmp.a[2][2]=0,tmp.a[3][2]=v;
modify(1,1,n,l,r,tmp); //tmp: 转移矩阵
}
else{
memset(ans,0,sizeof(ans)),query(1,1,n,l,r);
for(int i=0;i<3;i++)
printf("%d%c",ans[i],i==2?'\n':' ');
}
}
return 0;
}

「THUSCH 2017」大魔法师的更多相关文章

  1. 「THUSCH 2017」大魔法师 解题报告

    「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...

  2. LOJ 2980 「THUSCH 2017」大魔法师——线段树

    题目:https://loj.ac/problem/2980 线段树维护矩阵. 然后是 30 分.似乎是被卡常了?…… #include<cstdio> #include<cstri ...

  3. @loj - 2977@ 「THUSCH 2017」巧克力

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 「人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道.」 明 ...

  4. LOJ #2978「THUSCH 2017」杜老师

    听说LOJ传了THUSC题赶紧上去看一波 随便点了一题都不会做想了好久才会写暴力爆了一发过了... LOJ #2978 题意 $ T$次询问,每次询问$ L,R$,问有多少种选取区间中数的方案使得选出 ...

  5. loj#2978. 「THUSCH 2017」杜老师(乱搞)

    题面 传送门 题解 感谢yx巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...

  6. LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)

    题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...

  7. LOJ 2979 「THUSCH 2017」换桌——多路增广费用流

    题目:https://loj.ac/problem/2979 原来的思路: 优化连边.一看就是同一个桌子相邻座位之间连边.相邻桌子对应座位之间连边. 每个座位向它所属的桌子连边.然后每个人建一个点,向 ...

  8. LOJ 2978 「THUSCH 2017」杜老师——bitset+线性基+结论

    题目:https://loj.ac/problem/2978 题解:https://www.cnblogs.com/Paul-Guderian/p/10248782.html 第 i 个数的 bits ...

  9. LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树

    题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...

随机推荐

  1. 学习java 7.18

    学习内容: Lambda表达式的格式:(形式参数)  ->  {代码块} 如果有多个参数,参数之间用逗号隔开 new Thread(  ()   ->   { System.out.pri ...

  2. Spark(七)【RDD的持久化Cache和CheckPoint】

    RDD的持久化 1. RDD Cache缓存 ​ RDD通过Cache或者Persist方法将前面的计算结果缓存,默认情况下会把数据以缓存在JVM的堆内存中.但是并不是这两个方法被调用时立即缓存,而是 ...

  3. ssh : connect to host XXX.XXX.XXX.XXX port : 22 connect refused

    初学者 写博客 如有不对之处请多多指教 我是要在俩个主机的俩个虚拟机上 用scp (security copy)进行文件远程复制. 但是 终端 提示 ssh : connect to host XXX ...

  4. [学习总结]4、Android的ViewGroup中事件的传递机制(一)

    本文主要针对dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent三个方法,通过简单的例子来简单的介绍下. 根据字面意思的理解,dispatchTo ...

  5. Insert into select语句引发的生产事故

    前言   Insert into select请慎用.这天xxx接到一个需求,需要将表A的数据迁移到表B中去做一个备份.本想通过程序先查询查出来然后批量插入.但xxx觉得这样有点慢,需要耗费大量的网络 ...

  6. Linux基础命令---sendmail发送邮件

    sendmail sendmail是postfix中的一个发送邮件的代理程序,它负责发送邮件到远程服务器,并且可以接收邮件.sendmail在发送邮件的时候,默认从标砖输入读取内容,以".& ...

  7. redis入门到精通系列(七):redis高级数据类型详解(BitMaps,HyperLogLog,GEO)

    高级数据类型和五种基本数据类型不同,并非新的数据结构.高级数据类型往往是用来解决一些业务场景. (一)BitMaps (1.1) BitMaps概述 在应用场景中,有一些数据只有两个属性,比如是否是学 ...

  8. 一个超简单的Microsoft Edge Extension

    这个比微软官网上的例子简单很多,适合入门.总共4个文件: https://files.cnblogs.com/files/blogs/714801/cet6wordpicker.zip 36KB 1. ...

  9. Mysql资料 用户权限详解

    目录 一.MySQL权限详解 设置MySQL用户资源限制 用户资源限制执行操作 二.MySQL权限级别介绍 MySQL权限级别 MySQL创建权限 MySQL删除与插入权限 MySQL修改与触发器权限 ...

  10. 【WP】攻防世界-杂项-Misc

    长期更新一波 攻防世界 的杂项题解 这东西主要靠积累吧 攻防世界:https://adworld.xctf.org.cn 因为攻防世界的题目顺序经常变化,我也不改序号了,顺着之前写的位置往下写,推荐使 ...