LG P9844 [ICPC 2021 Nanjing R] Paimon Segment Tree Solution

Description

给定序列 a = ( a 1 , a 2 , ⋯ , a n ) a=(a_1,a_2,\cdots,a_n) a=(a1,a2,,an),有 m m m 次修改 ( l , r , v ) (l,r,v) (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.

执行完所有修改后,进行 q q q 次查询 ( l , r , L , R ) (l,r,L,R) (l,r,L,R),你需要求出 a l ∼ a r a_l\sim a_r alar 在第 [ L , R ] [L,R] [L,R] 秒间的历史平方和,对 1 0 9 + 7 10^9+7 109+7 取模.
初始时为第 0 0 0 秒,第 i i i 次修改发生在第 i i i 秒.

Limitations

1 ≤ n , m , q ≤ 5 × 1 0 4 1\le n,m,q\le 5\times 10^4 1n,m,q5×104
1 ≤ l ≤ r ≤ n 1\le l\le r\le n 1lrn
0 ≤ L ≤ R ≤ m 0\le L\le R\le m 0LRm
∣ a i ∣ , ∣ v ∣ < 1 0 9 + 7 |a_i|,|v|<10^9+7 ai,v<109+7
4 s , 256 MB 4\text{s},256\text{MB} 4s,256MB

Solution

首先将询问拆成 [ 0 , y ] [0,y] [0,y] [ 0 , x − 1 ] [0,x-1] [0,x1],在时间轴上做扫描线.
然后需要一个 ds,支持区间加,区间历史平方和.
需要维护很多 tag \textit{tag} tag,考虑矩阵,维护区间长度 l e n len len,区间和 s 1 s_1 s1,区间平方和 s 2 s_2 s2,历史平方和 h h h.
左行右列的口诀,不难推导出转移矩阵:

  • 标记一个版本: [ l , s 1 , s 2 , h ] × [ 1 , 0 , 0 , 0 0 , 1 , 0 , 0 0 , 0 , 1 , 1 0 , 0 , 0 , 1 ] = [ l , s 1 , s 2 , h ′ ] \begin{bmatrix}l,s_1,s_2,h\end{bmatrix}\times\begin{bmatrix}1,0,0,0\\0,1,0,0\\0,0,1,1\\0,0,0,1\end{bmatrix}=\begin{bmatrix}l,s_1,s_2,h^\prime\end{bmatrix} [l,s1,s2,h]× 1,0,0,00,1,0,00,0,1,10,0,0,1 =[l,s1,s2,h]
  • 区间加 v v v [ l , s 1 , s 2 , h ] × [ 1 , v , v 2 , v 2 0 , 1 , 2 v , 2 v 0 , 0 , 1 , 0 0 , 0 , 0 , 1 ] = [ l , s 1 , s 2 , h ′ ] \begin{bmatrix}l,s_1,s_2,h\end{bmatrix}\times\begin{bmatrix}1,v,v^2,v^2\\0,1,2v,2v\\0,0,1,0\\0,0,0,1\end{bmatrix}=\begin{bmatrix}l,s_1,s_2,h^\prime\end{bmatrix} [l,s1,s2,h]× 1,v,v2,v20,1,2v,2v0,0,1,00,0,0,1 =[l,s1,s2,h]

然后直接套 P7453 的矩阵线段树即可(甚至矩阵大小都一样).
常数方面,如果你 P7453 的代码能稳过,应该没什么问题.
时间复杂度 O ( k 3 ( m + q ) log ⁡ n ) O(k^3(m+q)\log n) O(k3(m+q)logn),其中 k = 4 k=4 k=4.

Code

5.54 KB , 0.99 s , 18.14 MB (maximum,C++20 with O2) 5.54\text{KB},0.99\text{s},18.14\text{MB}\;\texttt{(maximum,C++20 with O2)} 5.54KB,0.99s,18.14MB(maximum,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;
}namespace fastio {}
using fastio::read;
using fastio::write;constexpr int mod = 1e9 + 7;
inline int add(int x, int y) {return x + y >= mod ? x + y - mod : x + y; }namespace matrix {}
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<int>& 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();}void build(int u, int l, int r, const vector<int>& a) {tr[u].l = l, tr[u].r = r;if (l == r) {tr[u].val[0][0] = 1;tr[u].val[0][1] = add(a[l], mod);tr[u].val[0][2] = tr[u].val[0][3] = 1LL * a[l] * a[l] % mod;return;}const int mid = (l + r) >> 1;build(ls(mid), l, mid, a);build(rs(mid), mid + 1, r, a);pushup(u, mid);}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); }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;}inline void range_mul(int l, int r, const Mat& mat) { modify(0, l, r, mat); }inline Mat range_sum(int l, int r) { return query(0, l, r); }};
}
using seg_tree::SegTree;struct Query {int l, r, t, id;inline Query() {}inline Query(int _l, int _r, int _t, int _id) : l(_l), r(_r), t(_t), id(_id) {}
};signed main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);const int n = read<int>(), m = read<int>(), q = read<int>();vector<int> a(n), sum(n);for (int i = 0; i < n; i++) {a[i] = read<int>();sum[i] = add(i ? sum[i - 1] : 0, 1LL * a[i] * a[i] % mod);}vector<int> L(m), R(m), X(m);for (int i = 0; i < m; i++) {L[i] = read<int>(), R[i] = read<int>(), X[i] = read<int>();L[i]--, R[i]--;}vector<vector<Query>> adj(m + 1);for (int i = 0, l, r, x, y; i < q; i++) {l = read<int>(), r = read<int>(), x = read<int>(), y = read<int>(), l--, r--;adj[y].emplace_back(l, r, 1, i);if (x > 0) adj[x - 1].emplace_back(l, r, -1, i);}Mat A; A[2][3] = 1;SegTree sgt(a);vector<int> ans(q);for (auto & [l, r, t, id] : adj[0]) {ans[id] = add(ans[id], add(add(sum[r] - (l > 0 ? sum[l - 1] : 0), mod) * t, mod));}for (int i = 0; i < m; i++) {Mat tmp;tmp[0][1] = add(X[i], mod);tmp[0][2] = tmp[0][3] = 1LL * X[i] * X[i] % mod;tmp[1][2] = tmp[1][3] = 2LL * add(X[i], mod) % mod;tmp[2][3] = 1;sgt.range_mul(L[i], R[i], tmp);if (L[i] > 0) sgt.range_mul(0, L[i] - 1, A);if (R[i] < n - 1) sgt.range_mul(R[i] + 1, n - 1, A);for (auto & [l, r, t, id] : adj[i + 1]) {ans[id] = add(ans[id], add(sgt.range_sum(l, r)[0][3] * t, mod));}}for (int i = 0; i < q; i++) {write(ans[i]);putchar_unlocked('\n');}return 0;
}

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

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

相关文章

Google Prompt Tuning:文本嵌入优化揭秘

Google Research Prompt Tunin :from_embedded_string 在 Google Research 的 Prompt Tuning 项目代码库 中,from_embedded_string 函数主要用于基于字符串文本初始化提示词的嵌入向量,其调用场景通常与提示词优化或任务适配相关。 1. 核心代码位置 from_embedded_string …

网页 H5 微应用接入钉钉自动登录

ℹ️关于云审批 云审批&#xff08;cloud approve&#xff09; &#xff0c;一款专为小微企业打造&#xff0c;支持多租户的在线审批神器。它简化了申请和审批流程&#xff0c;让您随时随地通过手机或电脑完成请款操作。员工一键提交申请&#xff0c;审批者即时响应&#xff0c…

idea无法识别Maven项目

把.mvn相关都删除了 导致Idea无法识别maven项目 或者 添加导入各个模块 最后把父模块也要导入

飞桨paddle import fluid报错【已解决】

跟着飞桨的安装指南安装了paddle之后 pip install paddlepaddle有一个验证&#xff1a; import paddle.fluid as fluid fluid.install check.run check()报错情况如下&#xff0c;但是我在pip list中&#xff0c;确实看到了paddle安装上了 我import paddle别的包&#xff0c…

现代化SQLite的构建之旅——解析开源项目Limbo

现代化SQLite的构建之旅——解析开源项目Limbo 在当今飞速发展的技术世界中,轻量级且功能强大的数据库已成为开发者的得力助手。当我们谈论轻量级数据库时,SQLite无疑是一个举足轻重的名字。然而,随着技术的进步,我们对数据库的需求也变得更加多样化。这正是Limbo项目诞生…

MinIO:从入门到精通,解锁云原生存储的奥秘

一、引言&#xff1a;为什么 MinIO 正在重塑存储世界&#xff1f; 在云计算和大数据时代&#xff0c;传统存储系统面临扩展性差、成本高、兼容性不足等挑战。MinIO 凭借其 S3 兼容性、分布式架构、高性能存储 等特性&#xff0c;成为企业构建现代化存储基础设施的首选。 本文…

vscode怎么关闭自动定位文件

关闭自动定位文件功能 方式1 在设置中搜索: explorer.autoReveal 方式2 直接在settings.json中增加"explorer.autoReveal": false 添加类似jetbrains IDE的文件定位功能 可以直接安装插件市场搜索niushuaibing.vs-location, 安装后会有文件定位按钮, 点击后即可…

学习路之uniapp--unipush2.0推送功能--给自己发通知

学习路之uniapp--unipush2.0推送功能--给自己发通知 一、绑定云空间及创建云函数二、编写发送界面三、效果后期展望&#xff1a; 一、绑定云空间及创建云函数 package.json {"name": "server-push","dependencies": {},"main": "…

什么是VR展示?VR展示的用途

随着科技的迅猛发展&#xff0c;我们步入一个全新的数字时代。在这个时代&#xff0c;虚拟现实&#xff08;VR&#xff09;技术崭露头角&#xff0c;逐步改变我们对世界的认知。全景展示厅作为VR技术与传统展览艺术的完美结合&#xff0c;以独特的全景视角&#xff0c;引领我们…

抖音IP属地跟无线网有关吗?如何更改

IP属地显示功能让许多用户感到好奇——为什么自己的位置信息有时准确&#xff0c;有时却显示在其他城市&#xff1f;这时&#xff0c;用户会疑惑&#xff1a;抖音IP属地跟无线网有关系吗&#xff1f;抖音的IP属地显示与其所使用的网络类型&#xff08;包括无线网&#xff09;密…

JESD204 ip核使用与例程分析(二)

JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…

微软全新开源的Agentic Web网络项目:NLWeb,到底是什么 ?

目录 1、背景 2、NLWeb是什么&#xff1f; 3、NLWeb是如何工作的&#xff1f; 3.1 技术原理 3.2 对发布者的价值 3.3 核心团队与合作伙伴 4、快速入门指南 5、延伸阅读 Agentic&#xff1a;Agent的形容词&#xff0c;Agentic指系统由大型语言模型&#xff08;LLM&#…

前端性能优化的秘密武器:Preload 与 Prefetch 的深度解析

前端性能优化的秘密武器&#xff1a;Preload 与 Prefetch 的深度解析 在前端开发中&#xff0c;页面加载速度直接影响用户体验和业务转化率。而“资源预加载”技术&#xff0c;正是优化加载性能的核心手段之一。本文将深入浅出地讲解 Preload 与 Prefetch 这两项技术&#xff…

App Builder技术选型指南:从AI编程到小程序容器,外卖App开发实战

在2025年快速迭代的技术生态中&#xff0c;开发者构建App的路径愈发多样化。本文以开发一个同城外卖App为例&#xff0c;对比当前主流的AI编程工具&#xff08;如Cursor、GitHub Copilot、Trae&#xff09;与小程序容器技术&#xff08;如FinClip&#xff09;的优劣势、难易度及…

深度学习入门到实战:用PyTorch打通数学、张量与模型训练全链路​

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 一. 人工智能、机器学习与深度学习的关系 1.1 概念层次解析 人工智能&#xff08;AI&#xff09;&#xff1a;使机器模拟人类智能的广义领域 机器学…

windows服务器部署jenkins工具(一)

jenkins作为一款常用的构建发布工具&#xff0c;极大的简化了项目部署发布流程。jenkins通常是部署在linux服务上&#xff0c;今天给大家分享的是windows服务器上如何搭建jenkins发布工具。 1.首先第一步还是看windows安装docker 这篇文章哈&#xff0c;当然也可以不采用docke…

前端开发规范性利器系列之:ESLint

前言 我是一名从事低代码平台研发的前端CV程序猿&#xff0c;有几十名像我一样的小伙伴协同研发。在长期的多人协作和滚动迭代中&#xff0c;不出意外&#xff0c;代码中会充斥各种“坏味道”&#xff0c;如代码风格不统一、扩展性和灵活性降低等问题。我们是如何解决这些问题的…

数据结构知识点汇总

1、在数据结构中&#xff0c;随机访问是指能够直接访问任一元素&#xff0c;而不需要从特定的起始位置开始&#xff0c;也不需要按顺序访问其他元素。这种访问方式通常不涉及遍历。例如&#xff0c;数组&#xff08;array&#xff09;支持随机访问&#xff0c;你可以直接通过索…

ubuntu中上传项目至GitHub仓库教程

一、到github官网注册用户 1.注册用户 地址&#xff1a;https://github.com/ 2.安装Git 打开终端&#xff0c;输入指令git,检查是否已安装Git 如果没有安装就输入指令 sudo apt-get install git 二、上传项目到github 1.创建项目仓库 进入github主页&#xff0c;点击号…

C#在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案

在 .NET 9.0 中启用二进制序列化&#xff1a;配置、风险与替代方案 引言一、启用二进制序列化的步骤二、实现序列化与反序列化三、安全风险与缓解措施四、推荐替代方案五、总结 引言 在 .NET 生态中&#xff0c;二进制序列化&#xff08;Binary Serialization&#xff09;曾是…