P7453 [THUSC 2017] 大魔法师 Solution

Description

给定序列 a = ( a 1 , a 2 , ⋯ , a n ) a=(a_1,a_2,\cdots,a_n) a=(a1,a2,,an) b = ( b 1 , b 2 , ⋯ , b n ) b=(b_1,b_2,\cdots,b_n) b=(b1,b2,,bn) c = ( c 1 , c 2 , ⋯ , c n ) c=(c_1,c_2,\cdots,c_n) c=(c1,c2,,cn),有 m m m 个操作分七种:

  • e x c a ⁡ ( l , r ) \operatorname{exc_a}(l,r) exca(l,r):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 a i ← a i + b i a_i\gets a_i+b_i aiai+bi.
  • e x c b ⁡ ( l , r ) \operatorname{exc_b}(l,r) excb(l,r):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 b i ← b i + c i b_i\gets b_i+c_i bibi+ci.
  • e x c c ⁡ ( l , r ) \operatorname{exc_c}(l,r) excc(l,r):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 c i ← c i + a i c_i\gets c_i+a_i cici+ai.
  • add ⁡ ( l , r , v ) \operatorname{add}(l,r,v) add(l,r,v):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 a i ← a i + v a_i\gets a_i+v aiai+v.
  • mul ⁡ ( l , r , v ) \operatorname{mul}(l,r,v) mul(l,r,v):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 b i ← b i × v b_i\gets b_i\times v bibi×v.
  • assign ⁡ ( l , r , v ) \operatorname{assign}(l,r,v) assign(l,r,v):对每个 i ∈ [ l , r ] i\in[l,r] i[l,r] 执行 c i ← v c_i\gets v civ.
  • query ⁡ ( l , r ) \operatorname{query}(l,r) query(l,r):求 ∑ i = l r a i \sum\limits_{i=l}^r a_i i=lrai ∑ i = l r b i \sum\limits_{i=l}^r b_i i=lrbi ∑ i = l r c i \sum\limits_{i=l}^r c_i i=lrci的值,对 998244353 998244353 998244353 取模.

Limitations

1 ≤ n , m ≤ 2.5 × 1 0 5 1\le n,m\le 2.5\times 10^5 1n,m2.5×105
0 ≤ a i , b i , c i , v < 998244353 0\le a_i,b_i,c_i,v<998244353 0ai,bi,ci,v<998244353
1 ≤ l ≤ r ≤ n 1\le l\le r\le n 1lrn
5 s , 500 MB 5\text{s},500\text{MB} 5s,500MB

Solution

显然需要矩阵,由于要加常数,每个节点维护矩阵 [ a , b , c , 1 ] \begin{bmatrix}a,b,c,1\end{bmatrix} [a,b,c,1].
然后考虑用矩阵表达修改,由左行右列的口诀,显然有:

  • [ a , b , c , 1 ] × [ 1 , 0 , 0 , 0 1 , 1 , 0 , 0 0 , 0 , 1 , 0 0 , 0 , 0 , 1 ] = [ a + b , b , c , 1 ] \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} [a,b,c,1]× 1,0,0,01,1,0,00,0,1,00,0,0,1 =[a+b,b,c,1]
  • [ a , b , c , 1 ] × [ 1 , 0 , 0 , 0 0 , 1 , 0 , 0 0 , 1 , 1 , 0 0 , 0 , 0 , 1 ] = [ a , b + c , c , 1 ] \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} [a,b,c,1]× 1,0,0,00,1,0,00,1,1,00,0,0,1 =[a,b+c,c,1]
  • [ a , b , c , 1 ] × [ 1 , 0 , 1 , 0 0 , 1 , 0 , 0 0 , 0 , 1 , 0 0 , 0 , 0 , 1 ] = [ a , b , c + a , 1 ] \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,b,c,1]× 1,0,1,00,1,0,00,0,1,00,0,0,1 =[a,b,c+a,1]
  • [ a , b , c , 1 ] × [ 1 , 0 , 0 , 0 0 , 1 , 0 , 0 0 , 0 , 1 , 0 v , 0 , 0 , 1 ] = [ a + v , b , c , 1 ] \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} [a,b,c,1]× 1,0,0,00,1,0,00,0,1,0v,0,0,1 =[a+v,b,c,1]
  • [ a , b , c , 1 ] × [ 1 , 0 , 0 , 0 0 , v , 0 , 0 0 , 0 , 1 , 0 0 , 0 , 0 , 1 ] = [ a , b × v , c , 1 ] \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\times v,c,1\end{bmatrix} [a,b,c,1]× 1,0,0,00,v,0,00,0,1,00,0,0,1 =[a,b×v,c,1]
  • [ a , b , c , 1 ] × [ 1 , 0 , 0 , 0 0 , 1 , 0 , 0 0 , 0 , 0 , 0 0 , 0 , v , 1 ] = [ a , b , v , 1 ] \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} [a,b,c,1]× 1,0,0,00,1,0,00,0,0,00,0,v,1 =[a,b,v,1]

由于矩阵乘法满足结合律,可以用线段树维护,维护每个节点的矩阵与标记(也是一个矩阵),修改操作直接乘上对应矩阵,查询操作求矩阵和即可.

需要注意几点:

  • 要初始化为单位矩阵的地方,不要忘记初始化.
  • 矩阵乘法时,不计算一直为 0 0 0 的位置.
  • 如果是单位矩阵就不下传.

Code

3.85 KB , 27.95 s , 80.72 MB (in total, C++20 with O2) 3.85\text{KB},27.95\text{s},80.72\text{MB}\;\texttt{(in total, C++20 with O2)} 3.85KB,27.95s,80.72MB(in total, C++20 with O2)

#include <bits/stdc++.h>
using namespace std;using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;template<class T>
bool chmax(T &a, const T &b){if(a < b){ a = b; return true; }return false;
}template<class T>
bool chmin(T &a, const T &b){if(a > b){ a = b; return true; }return false;
}constexpr int mod = 998244353;
inline int add(int x, int y) {return x + y >= mod ? x + y - mod : x + y; }
namespace matrix {struct Mat {int mat[4][4];inline Mat(int _e = 1) { memset(mat, 0, sizeof mat); mat[0][0] = mat[1][1] = mat[2][2] = mat[3][3] = _e;}inline int* operator[](int i) { return mat[i]; }inline const int* operator[](int i) const { return mat[i]; }};inline Mat operator+(const Mat& x, const Mat& y) {Mat z(0);for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++) z[i][j] = add(x[i][j], y[i][j]);return z;}inline Mat operator*(const Mat& x, const Mat& y) {Mat z(0);for (int i = 0; i < 4; i++)for (int k = 0; k < 4; k++) {if (!x[i][k]) continue;for (int j = 0; j < 4; j++) {if (!y[k][j]) continue;z[i][j] = (z[i][j] + 1LL * x[i][k] * y[k][j]) % mod;}}return z;}inline bool operator==(const Mat& x, const Mat& y) {for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)if (x[i][j] != y[i][j]) return false;return true;}
}
using matrix::Mat;namespace seg_tree {struct Node {int l, r;Mat val, tag;};inline int ls(int u) { return 2 * u + 1; }inline int rs(int u) { return 2 * u + 2; }struct SegTree {vector<Node> tr;inline SegTree() {}inline SegTree(const vector<Mat>& a) {const int n = a.size();tr.resize(n << 1);build(0, 0, n - 1, a);}inline void pushup(int u, int mid) {tr[u].val = tr[ls(mid)].val + tr[rs(mid)].val;}inline void apply(int u, const Mat& mat) {tr[u].val = tr[u].val * mat;tr[u].tag = tr[u].tag * mat;}inline void pushdown(int u, int mid) {if (tr[u].tag == Mat()) return;apply(ls(mid), tr[u].tag);apply(rs(mid), tr[u].tag);tr[u].tag = Mat();}inline void build(int u, int l, int r, const vector<Mat>& a) {tr[u].l = l, tr[u].r = r;if (l == r) {tr[u].val = a[l];return;}const int mid = (l + r) >> 1;build(ls(mid), l, mid, a);build(rs(mid), mid + 1, r, a);pushup(u, mid);}inline void modify(int u, int l, int r, const Mat& mat) {if (l <= tr[u].l && tr[u].r <= r) return apply(u, mat);const int mid = (tr[u].l + tr[u].r) >> 1;pushdown(u, mid);if (l <= mid) modify(ls(mid), l, r, mat);if (r > mid) modify(rs(mid), l, r, mat);pushup(u, mid); }inline Mat query(int u, int l, int r) {if (l <= tr[u].l && tr[u].r <= r) return tr[u].val;const int mid = (tr[u].l + tr[u].r) >> 1;Mat res = Mat(0);pushdown(u, mid);if (l <= mid) res = res + query(ls(mid), l, r);if (r > mid) res = res + query(rs(mid), l, r);return res;}};
}
using seg_tree::SegTree;signed main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n; scanf("%d", &n);vector<Mat> a(n);for (int i = 0; i < n; i++) {scanf("%d %d %d", &a[i][0][0], &a[i][0][1], &a[i][0][2]);a[i][0][3] = 1;}SegTree sgt(a);int m; scanf("%d", &m);for (int i = 0, op, l, r; i < m; i++) {scanf("%d %d %d", &op, &l, &r), l--, r--;if (op == 7) {auto mat = sgt.query(0, l, r);printf("%d %d %d\n", mat[0][0], mat[0][1], mat[0][2]);}else {auto mat = Mat();if (op == 1) mat[1][0] = 1;if (op == 2) mat[2][1] = 1;if (op == 3) mat[0][2] = 1;if (op == 4) scanf("%d", &mat[3][0]);if (op == 5) scanf("%d", &mat[1][1]);if (op == 6) scanf("%d", &mat[3][2]), mat[2][2] = 0;sgt.modify(0, l, r, mat);}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/900196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免费送源码:Java+ssm+MySQL SpringBoot社区配送服务系统小程序 计算机毕业设计原创定制

摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;社区当然也不例外。社区配送服务系统小程序是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;…

SQL语句(一)—— DDL

目录 一、SQL 基础知识 &#xff08;一&#xff09;SQL 通用语法 &#xff08;二&#xff09;SQL 分类 二、DDL —— 数据库操作 1、查询所有数据库 2、查询当前数据库 3、创建数据库 4、删除数据库 5、切换数据库 三、DDL —— 表操作 &#xff08;一&#xff09;查…

【Android】界面布局-线性布局LinearLayout-例子

线性布局&#xff08;LinearLayout&#xff09;是一种重要的界面布局中&#xff0c;也是经常使用到的一种界面布局 • 在线性布局中&#xff0c;所有的子元素都按照垂直或水平的顺序在界面上排列 ➢如果垂直排列&#xff0c;则每行仅包含一个界面元素 ➢如果水平排列&…

leetcode数组-长度最小的子数组

题目 题目链接&#xff1a;https://leetcode.cn/problems/minimum-size-subarray-sum/ 给定一个含有 n个正整数的数组和一个正整数 target** 。** 找出该数组中满足其总和大于等于target的长度最小的 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度**…

一周学会Pandas2 Python数据处理与分析-Jupyter Notebook安装

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Jupyter (Project Jupyter | Home&#xff09;项目是一个非营利性开源项目&#xff0c;于2014年由IPython项目中诞生…

前端页面鼠标移动监控(鼠标运动、鼠标监控)鼠标节流处理、throttle、限制触发频率(setTimeout、clearInterval)

文章目录 使用lodashjs库手动实现节流&#xff08;通过判断之前设定的定时器setTimeout是否存在&#xff09; 使用lodashjs库 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Com…

java流程控制04:if选择结构

选择结构 if单选择结构 if双选择结构 if多选择结构 嵌套的if结构 switch多选择结构 if单选择结构 我们很多时候需要去判断一个东西是否可行&#xff0c;然后我们才去执行&#xff0c;这样一个过程在程序中用if语句来表示 语法&#xff1a; if(布尔表达式){//如果布尔表达…

在uniapp中,video比普通的标签层级高解决问题

<view style"position: relative;"><video style"position: absolute;z-index:-1"></video><view style"position: absolute;z-index:999"></view> </view> 上面代码并没有解决view的层级比video高的问题&…

基于R语言与MaxEnt的物种分布建模全流程解析:从算法优化到科研制图实战

随着全球气候变化与生物多样性保护需求的加剧&#xff0c;物种分布模型&#xff08;Species Distribution Model, SDM&#xff09;已成为生态学、保护生物学研究的核心工具。MaxEnt模型凭借其‌对小样本数据的强适应性‌和‌环境变量非线性关系的解析能力‌&#xff0c;成为SDM…

DPDI版本升级说明

Dispatch PDI v2.0.3版本升级说明 自Dispatch PDI社区版全新版本V2.0.0于2025 年3月25日发布以来&#xff0c;我们始终紧密关注用户动态&#xff0c;并全力协助用户线上完成从V0.0.4到V2.0.0的迁移工作。在短短一周内&#xff0c;我们成功助力约90%的用户完成了迁移。在此期间…

大钲资本押注儒拉玛特全球业务,累计交付超2500条自动化生产线儒拉玛特有望重整雄风,我以为它破产倒闭了,担心很多非标兄弟们失业

1. 交易概况 时间与主体:大钲资本于2025年4月1日正式宣布完成对儒拉玛特自动化技术(苏州)有限公司及其全球子公司和关联企业的收购。交易通过大钲资本旗下美元基金设立的儒拉玛特(新加坡)公司作为控股主体进行,交易金额未披露。 收购范围:包括儒拉玛特亚太、欧洲、北美等…

LabVIEW 调用 Python 函数

此程序是 LabVIEW 调用 Python 函数实现双精度数相加的典型示例。通过 LabVIEW 搭建交互框架&#xff0c;借助 “Open Python Session” 创建 Python 代码运行环境&#xff0c;定位 Python 模块路径后调用 “Add” 函数&#xff0c;最终实现数据处理并关闭会话。整个流程展现了…

基于SpringBoot的“考研学习分享平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“考研学习分享平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体功能结构图 局部E-R图 系统首页界面 …

恒盾C#混淆加密卫士 - 混淆加密保护C#程序

对于大部分C#开发者来说&#xff0c;写完代码点个发布就完事儿了&#xff0c;但你可能不知道——用记事本都能扒开你编译好的程序&#xff01;像dnSpy这类反编译工具&#xff0c;分分钟能把你的EXE/DLL变回原汁原味的源代码&#xff0c;商业机密赤裸裸曝光不说&#xff0c;竞争…

selectdb修改表副本

如果想修改doris&#xff08;也就是selectdb数据库&#xff09;表的副本数需要首先确定是否分区表&#xff0c;当前没有数据字典得知哪个表是分区的&#xff0c;只能先show partitions看结果 首先&#xff0c;副本数不应该大于be节点数 其次&#xff0c;修改期间最好不要跑业务…

【嵌入式-stm32电位器控制以及旋转编码器控制LED亮暗】

嵌入式-stm32电位器控制LED亮暗 任务1代码1Key.cKey.hTimer.cTimer.hPWM.cPWM.hmain.c 实验现象1任务2代码2Key.cKey.hmain.c 实验现象2问题与解决总结 源码框架取自江协科技&#xff0c;在此基础上做扩展开发。 任务1 本文主要介绍利用stm32f103C8T6实现电位器控制PWM的占空比…

图扑可视化点亮智慧城市垃圾分类新未来

图扑基于 HT 开发的智慧城市废弃物可视化管理系统&#xff0c;通过智能感知与三维可视化技术&#xff0c;构建全流程数字化监管平台。系统实现固体废物从源头投放到终端处置的全程可视化追踪&#xff0c;提供智能收运路径规划与资源回收管理方案&#xff0c;助力城市环境治理向…

Elasticsearch安全加固指南:启用登录认证与SSL加密

在之前文章中我们介绍了Elasticsearch安全与权限控制&#xff0c;本篇文章我们将详细介绍 启用登录认证与SSL加密实践配置操作 。 1 为什么需要安全加固&#xff1f; Elasticsearch默认不启用安全功能&#xff0c;会导致以下风险&#xff1a; 未授权访问&#xff1a;任何人都能…

前端知识点---本地存储(javascript)

localStorage 是浏览器提供的一个 本地存储 API&#xff0c;可以在用户的浏览器中存储数据&#xff0c;数据不会随页面刷新而丢失。 1. 基本用法 (1) 存储数据&#xff08;setItem&#xff09; localStorage.setItem("username", "zhangsan");存储 “use…

神经网络能不能完全拟合y=x² ???

先说结论&#xff1a;关键看激活函数的选择 ReLU神经网络对非线性函数的拟合分析 ReLU神经网络对非线性函数&#xff08;如 y x 2 y x^2 yx2&#xff09;的拟合只能是逼近&#xff0c;而无法实现数学意义上的完全重合。这一结论源于ReLU的分段线性本质与目标函数的非线性结…