当前位置: 首页 > news >正文

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.xdnf.cn/news/511543.html

相关文章:

  • Python编程入门:从安装到基础算法应用的完整指南
  • weibo_comment_pc_tool | 我于2025.5月用python开发的评论采集软件,根据帖子链接爬取评论的界面工具
  • UE5无法编译问题解决
  • 机器学习(13)——LGBM(2)
  • sparkSQL读入csv文件写入mysql(2)
  • 【微信小程序 + 高德地图API 】键入关键字搜索地址,获取经纬度等
  • 餐厅等位与核酸检测排队:用算法模拟生活中的等待
  • printf在c语言中代表什么(非常详细)
  • PyTorch音频处理技术及应用研究:从特征提取到相似度分析
  • OpenCV-python数学形态学
  • 《虚拟即真实:数字人驱动技术在React Native社交中的涅槃》
  • MongoDB的安装及简单使用
  • python3GUI--智慧交通分析平台:By:PyQt5+YOLOv8(详细介绍)
  • Python面试总结
  • [Java实战]Spring Boot整合RabbitMQ:实现异步通信与消息确认机制(二十七)
  • Text2SQL:自助式数据报表开发---0517
  • Win 11开始菜单图标变成白色怎么办?
  • Java 并发编程
  • discuz X3.5批量新建用户
  • Leetcode 3551. Minimum Swaps to Sort by Digit Sum
  • BAT32 Could not stop Cortex-M device
  • 如何根据三点求圆心
  • 多模态大语言模型arxiv论文略读(八十一)
  • 【Leetcode】取余/2的幂次方
  • ABP vNext 多租户系统实现登录页自定义 Logo 的最佳实践
  • CSS- 4.3 绝对定位(position: absolute)学校官网导航栏实例
  • LLM大语言模型系列1-token
  • Linux干货(六)
  • 机器学习-人与机器生数据的区分模型测试 - 模型选择与微调
  • Redis 学习笔记 4:优惠券秒杀