分析

在线段树上用\(4 \times 4\)的矩阵打标记。

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=250005;
const LL MOD=998244353;
int n,m,ql,qr;
LL a[MAXN],b[MAXN],c[MAXN];
struct Mat{
LL a[4][4];
Mat(){memset(a,0,sizeof a);}
inline LL* operator [] (int x){return a[x];}
inline friend Mat operator * (Mat x,Mat y){
Mat ret;
ret[0][0]=(ret[0][0]+x[0][0]*y[0][0])%MOD;
ret[0][1]=(ret[0][1]+x[0][0]*y[0][1])%MOD;
ret[0][2]=(ret[0][2]+x[0][0]*y[0][2])%MOD;
ret[0][3]=(ret[0][3]+x[0][0]*y[0][3])%MOD;
ret[0][0]=(ret[0][0]+x[0][1]*y[1][0])%MOD;
ret[0][1]=(ret[0][1]+x[0][1]*y[1][1])%MOD;
ret[0][2]=(ret[0][2]+x[0][1]*y[1][2])%MOD;
ret[0][3]=(ret[0][3]+x[0][1]*y[1][3])%MOD;
ret[0][0]=(ret[0][0]+x[0][2]*y[2][0])%MOD;
ret[0][1]=(ret[0][1]+x[0][2]*y[2][1])%MOD;
ret[0][2]=(ret[0][2]+x[0][2]*y[2][2])%MOD;
ret[0][3]=(ret[0][3]+x[0][2]*y[2][3])%MOD;
ret[0][0]=(ret[0][0]+x[0][3]*y[3][0])%MOD;
ret[0][1]=(ret[0][1]+x[0][3]*y[3][1])%MOD;
ret[0][2]=(ret[0][2]+x[0][3]*y[3][2])%MOD;
ret[0][3]=(ret[0][3]+x[0][3]*y[3][3])%MOD;
ret[1][0]=(ret[1][0]+x[1][0]*y[0][0])%MOD;
ret[1][1]=(ret[1][1]+x[1][0]*y[0][1])%MOD;
ret[1][2]=(ret[1][2]+x[1][0]*y[0][2])%MOD;
ret[1][3]=(ret[1][3]+x[1][0]*y[0][3])%MOD;
ret[1][0]=(ret[1][0]+x[1][1]*y[1][0])%MOD;
ret[1][1]=(ret[1][1]+x[1][1]*y[1][1])%MOD;
ret[1][2]=(ret[1][2]+x[1][1]*y[1][2])%MOD;
ret[1][3]=(ret[1][3]+x[1][1]*y[1][3])%MOD;
ret[1][0]=(ret[1][0]+x[1][2]*y[2][0])%MOD;
ret[1][1]=(ret[1][1]+x[1][2]*y[2][1])%MOD;
ret[1][2]=(ret[1][2]+x[1][2]*y[2][2])%MOD;
ret[1][3]=(ret[1][3]+x[1][2]*y[2][3])%MOD;
ret[1][0]=(ret[1][0]+x[1][3]*y[3][0])%MOD;
ret[1][1]=(ret[1][1]+x[1][3]*y[3][1])%MOD;
ret[1][2]=(ret[1][2]+x[1][3]*y[3][2])%MOD;
ret[1][3]=(ret[1][3]+x[1][3]*y[3][3])%MOD;
ret[2][0]=(ret[2][0]+x[2][0]*y[0][0])%MOD;
ret[2][1]=(ret[2][1]+x[2][0]*y[0][1])%MOD;
ret[2][2]=(ret[2][2]+x[2][0]*y[0][2])%MOD;
ret[2][3]=(ret[2][3]+x[2][0]*y[0][3])%MOD;
ret[2][0]=(ret[2][0]+x[2][1]*y[1][0])%MOD;
ret[2][1]=(ret[2][1]+x[2][1]*y[1][1])%MOD;
ret[2][2]=(ret[2][2]+x[2][1]*y[1][2])%MOD;
ret[2][3]=(ret[2][3]+x[2][1]*y[1][3])%MOD;
ret[2][0]=(ret[2][0]+x[2][2]*y[2][0])%MOD;
ret[2][1]=(ret[2][1]+x[2][2]*y[2][1])%MOD;
ret[2][2]=(ret[2][2]+x[2][2]*y[2][2])%MOD;
ret[2][3]=(ret[2][3]+x[2][2]*y[2][3])%MOD;
ret[2][0]=(ret[2][0]+x[2][3]*y[3][0])%MOD;
ret[2][1]=(ret[2][1]+x[2][3]*y[3][1])%MOD;
ret[2][2]=(ret[2][2]+x[2][3]*y[3][2])%MOD;
ret[2][3]=(ret[2][3]+x[2][3]*y[3][3])%MOD;
ret[3][0]=(ret[3][0]+x[3][0]*y[0][0])%MOD;
ret[3][1]=(ret[3][1]+x[3][0]*y[0][1])%MOD;
ret[3][2]=(ret[3][2]+x[3][0]*y[0][2])%MOD;
ret[3][3]=(ret[3][3]+x[3][0]*y[0][3])%MOD;
ret[3][0]=(ret[3][0]+x[3][1]*y[1][0])%MOD;
ret[3][1]=(ret[3][1]+x[3][1]*y[1][1])%MOD;
ret[3][2]=(ret[3][2]+x[3][1]*y[1][2])%MOD;
ret[3][3]=(ret[3][3]+x[3][1]*y[1][3])%MOD;
ret[3][0]=(ret[3][0]+x[3][2]*y[2][0])%MOD;
ret[3][1]=(ret[3][1]+x[3][2]*y[2][1])%MOD;
ret[3][2]=(ret[3][2]+x[3][2]*y[2][2])%MOD;
ret[3][3]=(ret[3][3]+x[3][2]*y[2][3])%MOD;
ret[3][0]=(ret[3][0]+x[3][3]*y[3][0])%MOD;
ret[3][1]=(ret[3][1]+x[3][3]*y[3][1])%MOD;
ret[3][2]=(ret[3][2]+x[3][3]*y[3][2])%MOD;
ret[3][3]=(ret[3][3]+x[3][3]*y[3][3])%MOD;
return ret;
}
inline friend Mat operator + (Mat x,Mat y){
Mat ret;
ret[0][0]=(x[0][0]+y[0][0])%MOD;
ret[0][1]=(x[0][1]+y[0][1])%MOD;
ret[0][2]=(x[0][2]+y[0][2])%MOD;
ret[0][3]=(x[0][3]+y[0][3])%MOD;
return ret;
}
inline bool check(){
if(a[0][0]!=1||a[1][1]!=1||a[2][2]!=1||a[3][3]!=1) return true;
if(a[0][1]||a[0][2]||a[0][3]||a[1][0]||a[1][2]||a[1][3]||a[2][0]||a[2][1]||a[2][3]||a[3][0]||a[3][1]||a[3][2]) return true;
return false;
}
}unit,optm[4],kk,seg[MAXN<<2],tag[MAXN<<2]; #define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1) inline void pushtag(int o,Mat y){
seg[o]=seg[o]*y;
tag[o]=tag[o]*y;
} inline void pushdown(int o){
if(!tag[o].check()) return;
pushtag(lc,tag[o]);
pushtag(rc,tag[o]);
tag[o]=unit;
} void build(int o,int l,int r){
tag[o]=unit;
if(l==r){
seg[o][0][0]=a[l];
seg[o][0][1]=b[l];
seg[o][0][2]=c[l];
seg[o][0][3]=1;
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
seg[o]=seg[lc]+seg[rc];
} void upd(int o,int l,int r){
if(ql<=l&&r<=qr){pushtag(o,kk);return;}
pushdown(o);
if(mid>=ql) upd(lc,l,mid);
if(mid<qr) upd(rc,mid+1,r);
seg[o]=seg[lc]+seg[rc];
} Mat query(int o,int l,int r){
if(ql<=l&&r<=qr) return seg[o];
pushdown(o);
if(mid<ql) return query(rc,mid+1,r);
else if(mid>=qr) return query(lc,l,mid);
else return query(lc,l,mid)+query(rc,mid+1,r);
} #undef mid
#undef lc
#undef rc int main(){
rin(i,0,3) unit[i][i]=1;
rin(i,1,3) optm[i]=unit;
optm[1][1][0]=1;
optm[2][2][1]=1;
optm[3][0][2]=1;
n=read();
rin(i,1,n) a[i]=read(),b[i]=read(),c[i]=read();
build(1,1,n);
m=read();
while(m--){
int opt=read();ql=read(),qr=read();
if(opt<=3) kk=optm[opt];
else if(opt==4) kk=unit,kk[3][0]=read();
else if(opt==5) kk=unit,kk[1][1]=read();
else if(opt==6) kk=unit,kk[2][2]=0,kk[3][2]=read();
else{
Mat ans=query(1,1,n);
printf("%lld %lld %lld\n",ans[0][0],ans[0][1],ans[0][2]);
continue;
}
upd(1,1,n);
}
return 0;
}

[THUSC2017]大魔法师:线段树的更多相关文章

  1. [LOJ#2980][THUSCH2017]大魔法师(线段树+矩阵)

    每个线段树维护一个行向量[A,B,C,len]分别是这个区间的A,B,C区间和与区间长度,转移显然. 以及此题卡常,稍微哪里写丑了就能100->45. #include<cstdio> ...

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

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

  3. LOJ2980 THUSC2017大魔法师(线段树+矩阵乘法)

    线段树每个节点维护(A,B,C,len)向量,操作即是将其乘上一个矩阵. #include<iostream> #include<cstdio> #include<cma ...

  4. 【BZOJ-4530】大融合 线段树合并

    4530: [Bjoi2014]大融合 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 280  Solved: 167[Submit][Status] ...

  5. [BZOI2014]大融合——————线段树进阶

    竟然改了不到一小时就改出来了, 可喜可贺 Description Solution 一开始想的是边两侧简单路径之和的乘积,之后发现这是个树形结构,简单路径数就是节点数. 之后的难点就变成了如何求线段树 ...

  6. zhw大神线段树姿势

    ; i<; i++) tree[i][]=tree[i][]=i; ; i>=; i--) tree[i][]=tree[i+i][], tree[i][]=tree[i+i+][]; v ...

  7. HDU 5091---Beam Cannon(线段树+扫描线)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5091 Problem Description Recently, the γ galaxies bro ...

  8. HDU1199 动态线段树 // 离散化

    附动态线段树AC代码 http://acm.hdu.edu.cn/showproblem.php?pid=1199 因为昨天做了一道动态线段树的缘故,今天遇到了这题没有限制范围的题就自然而然想到了动态 ...

  9. [CodeChef - STREETTA] The Street 李超线段树

    大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X ...

随机推荐

  1. CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference

    1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...

  2. pandas中的数据结构-DataFrame

    pandas中的数据结构-DataFrame DataFrame是什么? 表格型的数据结构 DataFrame 是一个表格型的数据类型,每列值类型可以不同 DataFrame 既有行索引.也有列索引 ...

  3. Luogu P3959 [NOIP2017]宝藏

    题目 STO rqy OTZ 首先这种题一看我们就知道可以爆搜. prim一眼假了,但是加个SA也能过. 所以我们来写状压. 记\(f_{i,j,S}\)表示起点到\(j\)距离为\(i\),我们现在 ...

  4. 什么是RESTful API、WSGI、pecan

    RESTful API REST的全称是Representational State Transfer(表征状态转移), 是Roy Fielding在他的博士论文Architectural Style ...

  5. CSS高度坍塌问题的原因以及解决办法

    原因: 在文档流中,父元素的高度默认是被子元素撑开的,也就是子元素多高,父元素就多高.但是当为子元素设置浮动以后,子元素会完全脱离文档流,此时将会导致子元素无法撑起父元素的高度,导致父元素的高度塌陷. ...

  6. vue+hbuilder 打包成移动app

    查看了很多网上写的改来改去都在手机上运行不起来,运行起来又是白屏:最后放弃,自己结合文档搞吧! 1. 项目目录下的config文件夹里的index.js文件中,将build对象下的assetsPubl ...

  7. Idea多模块工程创建——继承、聚合

    一.工程介绍 淘淘网上商城是一个综合性的B2C平台,类似京东商城.天猫商城.会员可以在商城浏览商品.下订单,以及参加各种活动. 管理员.运营可以在平台后台管理系统中管理商品.订单.会员等. 客服可以在 ...

  8. MSDN上对yield关键字的示例

    public class PowersOf2 { static void Main() { // Display powers of 2 up to the exponent of 8: , )) { ...

  9. python中的正则表达式的使用

    一.正则表达式简介 正则表达式的官方文档:https://www.runoob.com/regexp/regexp-tutorial.html 正则表达式:又称正规表示式.正规表示法.正规表达式.规则 ...

  10. Python杂章

    IDLE常用的快捷键: Ctrl+]:缩进代码 Ctrl+[:取消缩进 Alt+3:注释代码 Alt+4:去掉注释 F5:运行代码 Ctrl+Z:撤销一步 print('你好,Python!')