#线段树,矩阵乘法#洛谷 7453 [THUSCH2017] 大魔法师
分析
首先考虑如果修改操作都是单点修改怎么做,
以第一种修改为例那么就是
[ABC1]×[1,0,0,01,1,0,00,0,1,00,0,0,1]=[A+BBC1]
同理其它操作也能通过乘矩阵来维护,
考虑区间修改时询问为求和,那么只需要开懒标记即可
时间复杂度 O(43Qlog2n)
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=250011,mod=998244353;
typedef long long lll; int n;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
struct maix{
lll p[4][4];
inline maix operator *(const maix &t)const{
rr maix _t;
for (rr int i=0;i<4;++i)
for (rr int j=0;j<4;++j){
_t.p[i][j]=0;
for (rr int k=0;k<4;++k)
_t.p[i][j]+=p[i][k]*t.p[k][j];
_t.p[i][j]%=mod;
}
return _t;
}
}u,lazy[N<<2];
struct Four{
lll p[4];
inline Four operator +(const Four &t)const{
rr Four _t;
for (rr int i=0;i<4;++i)
_t.p[i]=p[i]+t.p[i]>=mod?p[i]+t.p[i]-mod:p[i]+t.p[i];
return _t;
}
}ANS,w[N<<2];
inline bool Is_Unit(maix A){
for (rr int i=0;i<4;++i)
for (rr int j=0;j<4;++j)
if (A.p[i][j]!=u.p[i][j]) return 0;
return 1;
}
inline Four mul(Four A,maix B){
rr Four C;
for (rr int i=0;i<4;++i){
C.p[i]=0;
for (rr int j=0;j<4;++j)
C.p[i]+=A.p[j]*B.p[j][i];
C.p[i]%=mod;
}
return C;
}
inline void pdown(int k){
w[k<<1]=mul(w[k<<1],lazy[k]);
lazy[k<<1]=lazy[k<<1]*lazy[k];
w[k<<1|1]=mul(w[k<<1|1],lazy[k]);
lazy[k<<1|1]=lazy[k<<1|1]*lazy[k];
lazy[k]=u;
}
inline void build(int k,int l,int r){
lazy[k]=u;
if (l==r){
for (rr int i=0;i<3;++i)
w[k].p[i]=iut();
w[k].p[3]=1;
return;
}
rr int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
w[k]=w[k<<1]+w[k<<1|1];
}
inline void update(int k,int l,int r,int x,int y,maix z){
if (l==x&&r==y) {w[k]=mul(w[k],z),lazy[k]=lazy[k]*z; return;}
rr int mid=(l+r)>>1; if (!Is_Unit(lazy[k])) pdown(k);
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
w[k]=w[k<<1]+w[k<<1|1];
}
inline Four query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return w[k];
rr int mid=(l+r)>>1; if (!Is_Unit(lazy[k])) pdown(k);
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y);
}
signed main(){
for (rr int i=0;i<4;++i) u.p[i][i]=1;
n=iut(),build(1,1,n);
for (rr int Q=iut();Q;--Q){
rr int opt=iut(),l=iut(),r=iut(),w=0; rr maix z=u;
if (opt<7){
if (opt>3) w=iut();
switch (opt){
case 1:{
z.p[1][0]=1;
break;
}
case 2:{
z.p[2][1]=1;
break;
}
case 3:{
z.p[0][2]=1;
break;
}
case 4:{
z.p[3][0]=w;
break;
}
case 5:{
z.p[1][1]=w;
break;
}
case 6:{
z.p[2][2]=0,z.p[3][2]=w;
break;
}
}
update(1,1,n,l,r,z);
}
else{
ANS=query(1,1,n,l,r);
for (rr int i=0;i<3;++i)
print(ANS.p[i]),putchar(i==2?10:32);
}
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
· 程序员转型AI:行业分析