P6109 [Ynoi2009] rprmq1

news/2024/10/4 8:15:07/文章来源:https://www.cnblogs.com/lalaouyehome/p/18446271

优美的数据结构题。

这题先修改再查询,基本明确了要使用扫描线做这道题。

我们将第一维视为时间,那么我们对于一个操作,将其变为时刻 \(l_1\) 时,在区间 \([l_2,r_2]\) 加上 \(x\),时刻 \(r_1+1\) 时,在区间 \([l_2,r_2]\) 减去 \(x\)

然后对于一个查询,相当于是要求区间 \([l_2,r_2]\) 在时刻 \([l_1,r_1]\) 中的历史版本和。直接维护非常的不优秀啊,考虑优化这个东西。

继续将问题简化,如果询问只有一段前缀,也就是询问都为以 \((1,r_1,l2,r2)\) 形式出现的该怎么做?

我们可以求历史版本和,将操作和询问挂在时刻上,边修改边查询即可。

而对于一段前缀,我们也可以用类似的办法,先完成所有时刻的操作,再开始求历史版本和,从时刻 \(n\)\(1\),边修改边查询,这样就可以完成一段后缀。

那么接下来启发我们对于一个查询将其劈成两半,分别查询。具体我们可以考虑取若干个中点,解决若干次询问的查询。

我们可以进行线段树分治,将区间挂在最小的能包含自己的线段树上,其实就是 \(l\le l_1\le mid< r_1\le r\)\(l,r,mid\) 分别为线段树节点的左节点,右节点,和中点,对于每个节点,每次先将 \([l,mid]\) 时刻的操作先完成,再进入线段树右节点,然后再处理挂在该节点上的询问的后半段,开始查询历史版本和,处理完这些询问后我们减去 \([mid+1,r]\) 的贡献,再处理询问的前半段,边查询边回撤 \([l,mid]\) 的操作,最后再进入左节点。这样,就能优美地处理完了所有询问。

最后讲讲线段树维护细节吧。开始查询历史版本和,其本质是让所有节点的维护历史版本的节点都等于当前的值,我们可以在要查询时打一个标记,但是标记是不能乱打的!如果我们像普通标记下传那样,就会存在一个区间加的标记与开始查询的标记产生冲突的问题,不信自己去分情况手玩一下,本人因为这个调了很久!这个时候我们可以在每次开始查询标记下传时先把区间加的标记下传就没问题了。

哦对了,注意是历史版本和,所以对于每个时刻一定要先将加的值小的操作先处理!

时间复杂度 \(\mathcal{O}(n\log^2n)\)

代码:

#include <bits/stdc++.h>
#define int long long
#define rep(i, l, r) for (int i = l; i <= r; ++ i)
#define rrp(i, l, r) for (int i = r; i >= l; -- i)
#define pii pair <int, int>
#define eb emplace_back
#define id(x, y) n * (x - 1) + y
#define ls p << 1
#define rs ls | 1
using namespace std;
constexpr int N = 5e5 + 5, M = (1ll << 31) - 1, P = 998244353, inf = 1e16;
constexpr double PI = acos (-1.0);
inline int rd () {int x = 0, f = 1;char ch = getchar ();while (! isdigit (ch)) {if (ch == '-') f = -1;ch = getchar ();}while (isdigit (ch)) {x = (x << 1) + (x << 3) + ch - 48;ch = getchar ();}return x * f;
}
int qpow (int x, int y) {int ret = 1;for (; y; y >>= 1, x = x * x % P) if (y & 1) ret = ret * x % P;return ret;
}
int mx[N], his[N];
bool sta[N];
int tag[N][3];
bool cov[N];
void add (int p, int k1, int k2) {his[p] = max (his[p], mx[p] + k2);mx[p] += k1;tag[p][1] = max (tag[p][1], tag[p][0] + k2);tag[p][0] += k1;
}
void cover (int p) {add (ls, tag[p][0], tag[p][1]);add (rs, tag[p][0], tag[p][1]);tag[p][0] = tag[p][1] = 0;tag[p][2] = 1;his[p] = mx[p], tag[p][1] = tag[p][0];
}
void psd (int p) {if (tag[p][2]) {cover (ls), cover (rs);tag[p][2] = 0;}add (ls, tag[p][0], tag[p][1]);add (rs, tag[p][0], tag[p][1]);tag[p][0] = tag[p][1] = 0;
}
void upd (int p, int l, int r, int L, int R, int k) {if (L <= l && r <= R) {add (p, k, k);return ;} int mid = l + r >> 1; psd (p);if (L <= mid) upd (ls, l, mid, L, R, k);if (R > mid) upd (rs, mid + 1, r, L, R, k);mx[p] = max (mx[ls], mx[rs]);his[p] = max (his[ls], his[rs]);
}
int qry (int p, int l, int r, int L, int R) {if (L <= l && r <= R) return his[p];int ret = 0, mid = l + r >> 1;psd (p);if (L <= mid) ret = max (ret, qry (ls, l, mid, L, R));if (R > mid) ret = max (ret, qry (rs, mid + 1, r, L, R));return ret;
}
int n, m, q;
class oper {public:int l, r, k;friend bool operator < (const oper &a, const oper &b) {return a.k < b.k;}
} ;
vector <oper> vec[50005], vvc[50005];
int ans[N];
class ask {public:int l1, r1, l2, r2, i; 
} ;
bool cmp1 (ask o, ask p) {return o.r1 < p.r1;
}
bool cmp2 (ask o, ask p) {return o.l1 > p.l1;
}
vector <ask> vc[N];
void insert (int p, int l, int r, ask x) {if (l == r) {vc[p].eb (x);return ;}int mid = l + r >> 1;if (x.r1 <= mid) insert (ls, l, mid, x);else if (x.l1 > mid) insert (rs, mid + 1, r, x);else vc[p].eb (x);
}
void solve (int p, int l, int r) {if (l == r) {if (! vc[p].size ()) return ;for (auto it : vec[l]) upd (1, 1, n, it.l, it.r, it.k);cover (1); for (auto it : vc[p]) {ans[it.i] = qry (1, 1, n, it.l2, it.r2);}for (auto it : vec[l]) upd (1, 1, n, it.l, it.r, - it.k);return ;}int mid = l + r >> 1;rep (i, l, mid) {for (auto it : vec[i]) {int L = it.l, R = it.r, k = it.k;upd (1, 1, n, L, R, k);}}solve (rs, mid + 1, r);for (auto it : vc[p]) {vvc[it.r1].eb ((oper) {it.l2, it.r2, it.i});}rep (i, mid + 1, r) {for (auto it : vec[i]) {int L = it.l, R = it.r, k = it.k;upd (1, 1, n, L, R, k);}if (i == mid + 1) cover (1);for (auto it : vvc[i]) {ans[it.k] = max (ans[it.k], qry (1, 1, n, it.l, it.r));} vvc[i].clear ();}rep (i, mid + 1, r) {for (auto it : vec[i]) {int L = it.l, R = it.r, k = it.k;upd (1, 1, n, L, R, - k);}}for (auto it : vc[p]) {vvc[it.l1].eb ((oper) {it.l2, it.r2, it.i});}cover (1);rrp (i, l, mid) {for (auto it : vvc[i]) {ans[it.k] = max (ans[it.k], qry (1, 1, n, it.l, it.r));}for (int j = vec[i].size (); j >= 0; -- j) {if (j == vec[i].size ()) continue;int L = vec[i][j].l, R = vec[i][j].r, k = vec[i][j].k;upd (1, 1, n, L, R, - k);// if(p==3)// cout<<L<<" "<<R<<" "<<-k<<" "<<i<<" "<<his[1]<<endl;} vvc[i].clear ();}solve (ls, l, mid);
}
signed main () {// freopen ("1.in", "r", stdin);// freopen ("1.out", "w", stdout);n = rd (), m = rd (), q = rd (); ++ n;rep (i, 1, m) {int l1 = rd (), l2 = rd (), r1 = rd (), r2 = rd (), x = rd ();vec[l1].eb ((oper) {l2, r2, x}), vec[r1 + 1].eb ((oper) {l2, r2, - x});}rep (i, 1, n) sort (vec[i].begin (), vec[i].end ());rep (i, 1, q) {int l1 = rd (), l2 = rd (), r1 = rd (), r2 = rd ();insert (1, 1, n, (ask) {l1, r1, l2, r2, i});}solve (1, 1, n);rep (i, 1, q) printf ("%lld\n", ans[i]);
}

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

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

相关文章

Cisco Secure Network Analytics 7.5.1 发布下载,新增功能概览

Cisco Secure Network Analytics 7.5.1 发布下载,新增功能概览Cisco Secure Network Analytics 7.5.1 发布下载,新增功能概览 Cisco Secure Network Analytics 7.5.1 - 领先的网络检测和响应 (NDR) 解决方案 Secure Network Analytics (formerly Stealthwatch) - Network Vis…

C++ lambda 捕获列表

▲《C++ Primer》 P352

读数据湖仓06数据集成

读数据湖仓06数据集成1. 数据湖仓中的数据集成 1.1. 数据湖仓的总体目标是为每一个人提供支持,包括从普通职员到CEO 1.2. 有了作为基础设施的基础数据,企业等组织才能实现真正的数据驱动 1.3. 提供组织所需的数据,最关键的一环在于提供集成的数据基础1.3.1. 只将数据扔进数据…

MSYS2 环境使用

在 Windows 环境下使用 rusqlite 库碰到了报错:由于 Windows 环境不如 Ubuntu 那样一个 apt install libsqlite3-dev 解决问题,所以采用 MSYS2 来从根源解决问题。 安装MSYS2 官网: WEB PAGE MSYS2 代理镜像下载地址:无 由于 MSYS2 自带的有国内镜像,所以按理说下载好无需配…

Echoism

Echoing reality Are your memories of me? Floating through a state, half asleep, never awake(never awake) I wont breathe in eternity Carrying your secrets feeling close to who you are Youre just beyond my reach A passing breeze, And your final moments se…

快乐数学1培养数学直觉

1 培养数学直觉我们最初接触一个概念时,会形成我们的直觉。而我们的直觉会影响我们对一门学科的喜爱程度。什么意思呢? 假设我们想给 “猫 ”下一个定义:古代的定义: 一种毛茸茸的动物,有爪子、牙齿、尾巴和四条腿,高兴时发出咕噜声,生气时发出嘶嘶声。 进化定义: 某一…

SciTech-Mathmatics-Markdown:List 嵌入 code block + LaTex: 论文写作、排版与使用 + 数学公式的输入方式

民主与共和 更好的共和度保障更高级的民主, 是因为 民主 与 共和 是统一的。 平衡态的“跃迁”是需要“吸收足够能量”, "改变"总是需要"成本"的。 在正确的方向上,每一天的学习是“质变飞跃”的必要。Markdown: List 嵌入 code block Code is possible …

简单讲讲上下界网络流

无源汇可行流 无源汇网络流一般不讨论最大流,因为它的流都是环流,分布在各个位置,一是不好统计,二是一般也没有意义。所以一般建图只需要求是否有可行解(但我也没遇到过求输出YES和NO的可行流题目,网上的博客也都只当做有源汇的前置知识讲了) 废话不多说,直接上图。第一…

Netflix 錯誤 NW-8-18

环境 PS5的奈飞,OpenWrt的树莓派做软路由解决方案 首先重置,如果不行,关机拔掉电源线等待三分钟,重试 Netflix。如果这篇文章对你有用,可以关注本人微信公众号获取更多ヽ(^ω^)ノ ~

Python算法学习

算法学习心得,源码均为Python实现目录绪论数据结构算法算法的特征算法的评价算法的时间复杂度算法的空间复杂度递归汉诺塔问题(递归调用)查找排序二分查找检查排序是否完成冒泡排序选择排序插入排序希尔排序(高级版插入排序)快速排序堆排序(二叉树)python中内置好的堆排…

数学建模学习

数学建模学习,包含各种常用模型和Matlab源码目录 目录目录评价类方法层次分析法搜索引擎算法步骤算法代码F4锁定单元格优劣解距离法算法步骤算法代码自输入权重代码基于熵权法权重的代码灰色关联分析传统数理统计的不足之处该方法的好处算法步骤算法代码基于灰色关联度权重的代…

下载、安装、配置 android-studio-2021.1.1.22-windows

软件安装包:图1 软件安装包提示删除已经存在的版本:图2 提示删除已经存在的版本根据提示选择是:图3 根据提示选择是继续安装:图4图5图6图7图8图9图10