题解:Luogu P2075 区间 LIS

news/2025/10/20 22:14:16/文章来源:https://www.cnblogs.com/P2441M/p/19153806

题意

给定长度为 \(n\) 的排列 \(p\)\(q\) 次询问 \(l,r\),求 \(p[l,r]\) 的 LIS 长度。\(1\leq n,q\leq 10^5\)

题解

挺牛的题。

考虑如何刻画 LIS。感觉上 DP 没有什么前途,考虑另一种经典的 \(\mathcal{O}(n\log{n})\) 求 LIS 的方法:维护 \(f_i\) 表示长度为 \(i\) 的 LIS 的最小结尾元素,初始时 \(\forall 1\leq i\leq n,f_i\leftarrow +\infty\),当添加元素 \(x\) 时,对于每个 \(f_i<x\)\(i\),令 \(f_{i+1}\leftarrow \min(f_{i+1},x)\)。注意到 \(f\) 单调不减,所以上述过程实际上等价于找到最小的 \(i\) 使得 \(f_i\geq x\),令 \(f_i\leftarrow x\)

简化这个过程:我们维护 \(S\) 表示 \(f\) 中所有非 \(+\infty\)\(f_i\),初始时 \(S\leftarrow\varnothing\),每次插入 \(x\) 时,若 \(\max\limits_{y\in S}y<x\),则向 \(S\) 中插入 \(x\),否则将 \(S\) 中最小的 \(\geq x\) 的元素改为 \(x\)。最终答案就是 \(|S|\)

回到原题,考虑对右端点 \(r\) 做扫描线,对每个左端点 \(l\) 维护 \(S_{l,r}\) 表示对 \(p[l,r]\) 中元素依次执行上述操作得到的集合。我们当然不可能直接存下来所有的 \(S\),考虑找一些性质。通过手玩样例,我们会发现 \(S_{l,r}\subseteq S_{l-1,r}\)\(|S_{l-1,r}|-|S_{l,r}|\leq 1\)

证明:令 \(S_1\leftarrow\varnothing,S_2\leftarrow \{p_{l-1}\}\),我们遍历 \(p[l,r]\) 中的每个元素,同时对 \(S_1,S_2\) 执行操作。不难看出,每次插入 \(x\) 时,若 \(p_{l-1}\) 没有成为最小的 \(\geq x\) 的元素,则始终有 \(S_2=S_1\cup\{p_{l-1}\}\);否则,\(S_2\)\(p_{l-1}\) 会被修改为 \(x\),且对于 \(S_1\)

  • \(S_1\) 中所有元素 \(<x\),则 \(x\) 插入到 \(S_1\) 中后,我们有 \(S_2=S_1\)
  • \(S_1\) 中存在元素 \(\geq x\),记最小的元素为 \(y\),则 \(S_1\)\(y\) 会被修改为 \(x\),此时我们有 \(S_2=S_1\cup\{y\}\),也就是说 \(y\) 会代替 \(x\) 成为新的元素来保持 \(S_1,S_2\) 间的差异。

可以看出,这样子不断将操作执行下去,要么 \(S_2\) 会在某个时刻变得与 \(S_1\) 相等,要么 \(S_2\) 始终保持 \(S_1\subseteq S_2\land |S_2|-|S_1|\leq 1\)\(\Box\)

根据这个性质,一个数 \(x\) 必然会在一段前缀的 \(l\) 对应的 \(S_{l,r}\) 中出现,由此,我们可以从值域上考虑,对于每个数 \(x\) 维护 \(a_x\) 表示最大的 \(l\) 使得 \(x\in S_{l,r}\)。那么询问 \([l,r]\) 的答案时,只需查询有多少 \(x\) 满足 \(a_x\geq l\) 即可。

考虑每次 \(r\leftarrow r+1\)\(a\) 的变化。令 \(v=p_r\),则显然 \(a_v\leftarrow r\)。进一步考察 \(v+1\),若 \(a_{v+1}>0\),也就是 \(v+1\) 在某些 \(S_{l,r}\) 中出现,则 \(a_{v+1}\leftarrow 0\)。对于 \(v+2\),考虑包含它的某个 \(S_{l,r}\),只有在 \(v+1\in S_{l,r}\)\(v+2\) 才不会被修改,因此若最开始时 \(a_{v+1}>0\),则 \(a_{v+2}\leftarrow a_{v+1}\),否则 \(a_{v+2}\leftarrow 0\)

以此类推,可以发现对 \(a\) 的影响形如:有一个值 \(x\),初始时 \(x\)\(0\),依次遍历 \(i=v+1,v+2,\cdots,n\)

  • \(a_i>x\),交换 \(a_i\)\(x\) 的值。

这其实就是回转寿司中的操作。

考虑分块。不妨先想整块怎么做。此时我们不妨只关注块中元素构成的可重集 \(S\) 的变化。设 \(S\) 中元素的最大值为 \(mx\),考虑不同的 \(x\) 带来的影响:

  • \(x\geq mx\):操作对该块没有影响。
  • \(x<mx\):此时我们会从 \(S\) 中删除 \(mx\),再插入 \(x\)。而 \(x\) 的值会对应变成 \(mx\)

于是我们只需在每个块上用一个大根堆维护 \(S\) 即可。

再来考虑散块怎么做。由于处理整块时我们只关心元素构成的可重集,所以每个位置对应的数我们并不清楚。考虑如何由整块上的所有操作构成的可重集 \(P=\{x_1,x_2,\cdots,x_m\}\),还原整块中每个位置对应的数。

不妨先考察整块中的第一个元素 \(a_p\) 如何变化。考虑 \(mn=\min\limits_{x\in P}x\),不难发现若 \(mn\geq a_p\) 则无事发生,否则 \(a_p\) 会变成 \(mn\),并且此时,我们可以等效地在 \(P\) 中用 \(a_p\) 代替 \(mn\)。对于 \(a_{p+1}\),同样考察 \(P\) 中最小值即可,以此类推。我们发现,我们完全可以用和刚才类似的方法维护这个过程,更具体地,我们用小根堆维护 \(P\),然后遍历块中元素对应更新即可。

我们用权值 BIT 维护 \(a\) 中的值,那么每次操作先在 \(a_v=r\) 上单点加,然后对于接下来的回转寿司操作,先在 \(0\) 上单点加 \(1\),然后在最后得到的 \(x\) 上单点减 \(1\) 即可。

设块长为 \(B\),则时间复杂度为 \(\mathcal{O}((B+\dfrac{n}{B})\log{n}+q\log{n})\),取 \(B=\sqrt{n}\) 即可 \(\mathcal{O}(\sqrt{n}\log{n}+q\log{n})\) 地解决本题。当然也可以用值域分块把 \(q\) 后面的 \(\log\) 搞掉,没啥必要就是了。

代码

int n, q, B, a[N], p[N], ans[N];
int bl[N], lb[BC], rb[BC];
priority_queue<int> P[BC];
priority_queue<int, vector<int>, greater<>> Q[BC];
struct Query { int id, l, r; } qr[N];struct BIT {int c[N];inline int query(int x) {int res = 0;for (++x; x <= n + 1; x += lowbit(x)) res += c[x];return res;}inline void add(int x, int v) { for (++x; x; x -= lowbit(x)) c[x] += v; }
} ft;inline void rebuild(int id) {auto &pq = Q[id];if (pq.empty()) return;int l = lb[id], r = rb[id];for (int i = l; i <= r; ++i)if (a[i] > pq.top()) pq.push(a[i]), a[i] = pq.top(), pq.pop();priority_queue<int, vector<int>, greater<>>().swap(pq);
}
inline int query(int l, int r, int x) {int b1 = bl[l], b2 = bl[r];if (b1 == b2) {rebuild(b1);for (int i = l; i <= r; ++i) if (a[i] > x) swap(a[i], x);return priority_queue<int>(a + lb[b1], a + rb[b1] + 1).swap(P[b1]), x;}rebuild(b1), rebuild(b2);for (int i = l; i <= rb[b1]; ++i) if (a[i] > x) swap(a[i], x);priority_queue<int>(a + lb[b1], a + rb[b1] + 1).swap(P[b1]);for (int i = b1 + 1, tp; i < b2; ++i) {if (x >= P[i].top()) continue;Q[i].push(x);P[i].push(x), x = P[i].top(), P[i].pop();}for (int i = lb[b2]; i <= r; ++i) if (a[i] > x) swap(a[i], x);return priority_queue<int>(a + lb[b2], a + rb[b2] + 1).swap(P[b2]), x;
}int main() {ios::sync_with_stdio(0), cin.tie(0);n = rd(), q = rd(), B = BL - 5;for (int i = 1; i <= n; ++i) p[i] = rd();for (int i = 1, l, r; i <= q; ++i) l = rd(), r = rd(), qr[i] = {i, l, r};for (int i = 1, j = 1; j <= n; ++i) {lb[i] = j, rb[i] = min(j + B - 1, n);priority_queue<int>(a + lb[i], a + rb[i] + 1).swap(P[i]);for (int u = rb[i]; j <= u; ++j) bl[j] = i;}sort(qr + 1, qr + q + 1, [](const Query &x, const Query &y) { return x.r < y.r; });ft.add(0, n);for (int i = 1, j = 1; i <= n; ++i) {int val = p[i];if (val < n) {int x = query(val + 1, n, 0);ft.add(x, -1), ft.add(0, 1);}int b = bl[val];rebuild(b);ft.add(a[val], -1), ft.add(a[val] = i, 1);priority_queue<int>(a + lb[b], a + rb[b] + 1).swap(P[b]);while (j <= q && qr[j].r == i) ans[qr[j].id] = ft.query(qr[j].l), ++j;}for (int i = 1; i <= q; ++i) cout << ans[i] << '\n';return 0;
}

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

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

相关文章

英语_阅读_2050 Space tourism_待读

It is 2050. Space tourism has become a reality. 现在是2050年。太空旅游已经成为现实。 So would you want to be a space tourist? 那么你想成为一名太空游客吗? Here, some middle school students share their…

题解:Luogu P10644 [NordicOI 2022] 能源网格 Power Grid

题意 给定 \(n,m\)。对于 \(n\times m\) 的网格 \(a\),定义 \[c_{i,j}=\left\lvert \sum_{k=1}^{n}a_{k,j}-\sum_{k=1}^{m}a_{i,k} \right\rvert \]现在给定 \(c\),构造一组合法的 \(a\)。数据保证有解。\(1\leq n,m…

题解:Luogu P10004 [集训队互测 2023] Permutation Counting 2

题意 给定 \(n\),对于所有 \(0\leq x,y<n\) 求有多少长度为 \(n\) 的排列 \(p\) 满足 \(\sum\limits_{i=1}^{n-1}[p_i<p_{i+1}]=x\) 且 \(\sum\limits_{i=1}^{n-1}[p^{-1}_i<p^{-1}_{i+1}]=y\),答案对给定的…

题解:Luogu P4143 采集矿石

题意 给定长度为 \(n\) 的字符串 \(s\) 和权值序列 \(v\)。求所有子串 \(s[l,r]\) 使得 \(s[l,r]\) 在所有子串去重后的字典序降序排名,恰好等于 \(v[l,r]\) 的区间和。\(1\leq n\leq 10^5\)。 题解 注意到固定左端点…

从18w到1600w播放量,我的一点思考。

你好呀,我是歪歪。 前几天我想要巩固一下共识算法这个知识点。 (先声明,这篇文章不深入讨论共识算法本身) 于是我在 B 站大学上搜索了“共识算法”这个词:我还特意按照播放量排序了一下,准备先找个播放量高点的视…

扣一个细节问题

请看下这个uint bits = 0; for (int y = 0; y < 5; y++) {for (int x = 0; x < 4; x++)bits |= b[y][x] << (y * 4 + x);}上面的代码把一个[5][4]的byte数组用bits表示,该数组里的元素非0即1. 在经典的Th…

10.20java作业

10.20java作业1.2.3.4.5. 结果Parent: myValue = 10 Child: myValue = 20 Child: myValue = 20 Child: myValue = 20 Child: myValue = 21 第一行输出:new Parent() 创建父类对象,调用父类的 printValue 方法,输出父…

题解:Luogu P14175 【MX-X23-T5】向死存魏

题意 给定长度为 \(n\) 的序列 \(a\) 和值域 \(V\)。有 \(m\) 次操作:给定 \(l,r,x\),将 \(a[l,r]\) 中 \(=x\) 的数改为 \(0\)。 给定 \(x\),在序列末尾添加 \(x\)。 给定 \(l\),查询最小的 \(r\) 使得 \(a[l,r]\…

软工第三次作业————结对作业

软工第三次作业————结对作业软工第三次作业--结对作业 软工第三次作业结对作业——实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能)项目作业 实现一个自动生成小学四则运算题目的…

Spring 常见注解

目录🧐 @Configuration 和 @Import 的核心区别详细解释1. @Configuration (配置类)2. @Import (引入)参考资料 🧐 @Configuration 和 @Import 的核心区别特性 @Configuration @Import主要目的 标记一个类是 Java 配…

题解:AtCoder ARC208C Mod of XOR

题意 给定 \(C,X\),构造一个 \(n(1\leq n<2^{60})\) 使得 \((n\oplus C)\bmod{n}=X\),或报告无解。多测,\(1\leq T\leq 2\times 10^5\),\(1\leq C,X<2^{30}\)。 题解 神人构造题。 显然要有 \(n>X\)。不妨…

题解:Luogu P6898 [ICPC 2014 WF] Metal Processing Plant

题意 给定 \(n\),对于每个 \(1\leq i,j\leq n\),给出 \(d(i,j)\)。对于集合 \(S\),定义 \(D(S)=\max\limits_{i,j\in S}d(i,j)\)。将 \(\{1,2,\cdots,n\}\) 划分为两个集合 \(A,B\),最小化 \(D(A)+D(B)\)。\(1\leq…

32-腾讯IM接入资料和定价

腾讯IM接入资料和定价信息 一、产品概述 腾讯云即时通信IM(Instant Messaging)是腾讯提供的企业级即时通讯服务,支持多种平台接入,包括Android、iOS、Web和小程序等。 二、定价信息 1. 基础服务资费体验版: 提供完…

题解:AtCoder ARC207A Affinity for Artifacts

题意 给定长度为 \(n\) 的序列 \(a\) 和一个数 \(X\),求有多少种 \(a\) 的重排 \(b\) 使得 \(\sum\limits_{i=1}^n\max(b_i-i+1,0)\leq X\)。\(1\leq n\leq 100\),\(1\leq a_i,X\leq 10^9\)。 题解 你说得对,但我怎…

题解:Luogu P9260 [PA 2022] Miny

题意 给定一棵 \(n\) 个点的树,第 \(i\) 条边 \((a_i,b_i)\) 有边权 \(c_i\),第 \(i\) 个点有一个爆炸半径 \(r_i\)。当一个点被引爆时,所有在该点爆炸半径范围内的点也会被引爆,这些新的被引爆的点也可能继续引爆…

题解:Luogu P13544 [OOI 2022] Serious Business

题意 给定一个 \(3\times n\) 的网格,每个格子 \((i,j)\) 内有一个数 \(a_{i,j}\)。一个人初始分数为 \(0\),在位置 \((1,1)\) 处,每次可以向右或向下走一格,目标是到达 \((3,n)\)。当走到格子 \((i,j)\) 时,这个…

题解:Luogu P14254 分割(divide)

题意 给定一棵 \(n\) 个点的树,设根节点 \(1\) 的深度为 \(1\)。给定 \(k\),求有多少从树中选出 \(k\) 个两两不同的节点,组成有序序列 \(b_1,\cdots,b_k\) 的方案,使得:对于每个 \(1\leq i<k\),\(1<d_{b_…

31_创蓝短信接入资料和定价

创蓝短信接入资料和定价 公司简介 创蓝云智为企业提供短信、语音外呼、闪验、号码检测、实名认证等通讯类产品,致力于让企业更高效高质量的获得用户及触达用户。 产品类型通知短信 会员营销短信 国际营销短信 验证码短…

构造单

题目来源 取模下序列构造 是否存在 \(3\) 个长度为 \(n\) 的 \([0,n)\) 的排列 \(a,b,c\),使得 \(a_i+b_i=c_i\mod n\) 遇到取模考虑奇偶性,不要像太复杂,考虑 \(n\) 为奇数的时候直接 \(a=b=~0,1,2,3,4,…\),\(c=…