首页 > 其他分享 >Temperature 题解

Temperature 题解

时间:2024-07-25 14:56:50浏览次数:7  
标签:Temperature int 题解 lst 端点 max gets sim

前言

题目链接:洛谷SPOJHydro & bzoj

题意简述

有一个长度为 \(n\) 的序列,每个位置值的范围为 \([L_i, R_i]\) 内,求原序列可能的最长不降子串长度。

题目分析

尝试找一些性质。发现,连续一段合法的区间,都能分成若干真正参与最长不降子串,以及紧跟着的若干包含 \(L_i\) 的位置。下图红色表示前者,黑色表示后者。

我们把右端点向右移动,左端点肯定不会向左移动,是一个双指针。我们记 \(l\) 是当前左端点,现在让 \(r \gets r + 1\),看看左端点如何变化。发现不够,还要记 \(lst\) 表示上一个出现红色段的位置。那么分为以下几个情况讨论。

  1. \(L_r \leq L_{lst} \leq R_r\):
    说明这是一个黑色段,不需要任何操作。
  2. \(L_r \geq L_{lst}\):
    说明遇到了一个新的红色段,贡献了最长不降子串,让 \(lst \gets r\)。
  3. 此时必有 \(R_r < L_{lst}\):
    说明遇到上图绿色段的情况。我们要在 \(lst + 1 \sim r\) 里重新挑选出一个 \(l'\) 和 \(lst'\)。

前两者都很好处理,思考怎么弄第 \(3\) 条。

发现关键都在每条线段的下端,如果 \(l \sim r\) 里 \(\max L_i > R_{r}\),那么一定是不合法的,因为是不能下降的。所以考虑用 ST 表维护区间最小 \(L\) 的位置。遇到情况 \(3\),先让 \(l' \gets lst\),当 \(\max L_{l' \sim r} > R_{r}\),将 \(l' \gets l' +1\),至于 \(lst'\),就是最终 \(\max L_{l' \sim r}\) 的那个位置。

时间复杂度 \(\Theta(n \log n)\),瓶颈在于 ST 表。

继续思考,发现合法区间 \(l \sim r\) 的充要条件也是 \(\forall i \in [l, r], \max L_{l \sim i} \leq R_i\)。那么不需要那么麻烦,直接上双指针。如果 \(\max L_{l \sim r} > R_r\),\(l \gets l + 1\)。正确性显然。但是时间复杂度还是 \(\Theta(n \log n)\),能不能去掉 ST 表呢?

发现,我们要维护滑动窗口的最值,所以,上单调队列。队列里 \(L\) 从大到小排序。统计答案时,上一次弹出队列的位置 \(+ 1\) 就是合法的最长的左端点。

时空都是线性的。

代码

// #pragma GCC optimize(3)
// #pragma GCC optimize("Ofast", "inline", "-ffast-math")
// #pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <iostream>
#include <cstdio>
using namespace std;

int n, L[1000010], R[1000010];
int Q[1000010], head = 1, tail;
int ans = 1;

signed main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d%d", &L[i], &R[i]);
    for (int i = 1; i <= n; ++i) {
        while (head <= tail && L[Q[head]] > R[i]) ++head;
        if (head <= tail) ans = max(ans, i - Q[head - 1]);
        while (head <= tail && L[Q[tail]] <= L[i]) --tail;
        Q[++tail] = i;
    }
	printf("%d", ans);
	return 0;
}

后记 & 反思

双指针,考虑好添加右端点后,怎么删去不合法的左端点。

标签:Temperature,int,题解,lst,端点,max,gets,sim
From: https://www.cnblogs.com/XuYueming/p/18322711

相关文章

  • [ABC318E]Sandwiches 题解
    题意给定一个序列\(A\),要求找有多少个三元组\((i,j,k)\)满足以下条件:\(1\lei<j<k\leN\)\(A_i=A_k\)\(A_i\neA_j\)思路相当于是找每两个相同的元素中有多少个不同的数字。例如:12131答案显然是4,即是\((1,2,3)(1,2,5)(1,4,5)(3,4,5)\)。用\(q[A[i]]\)......
  • [题解]CF117C Cycle
    思路发现最简单的方法就是直接枚举三个点,但是复杂度\(\Theta(n^3)\)无法接受。考虑枚举一个点,并确定它的一条边,那么只需要再枚举一个点了。于是转化为了,对于每一个点找到其最好的出边。观察下图,\(a\toc\)的边是不必要的。因为,如果有一个三元环包含\(a\toc\),那么一定能......
  • P3294 [SCOI2016] 背单词 题解
    题意给你\(n\)个字符串,让你对其进行排列,使得按以下规则花费最少:设当前字符串为\(s\),\(x\)为\(s\)在答案排列中的位置。如果\(s\)存在后缀且\(s\)的后缀在\(s\)之后,花费加\(n^2\)。如果\(s\)不存在后缀则花费加\(x\)。设\(y\)为\(s\)之前离其最近的......
  • P10717 题解
    好神仙的题目。赛时胡了一个状态和转移都和官解不同的做法,得到了\(O(n10^m)\)的优秀复杂度。卡了一场常卡进了\(75\)分。这个做法和官解关系不大,并且很难进行最后的优化部分,所以在此不再赘述。首先考虑\(k=1\)的情况。考虑记录一些状态能够描述子树内的选择方案,\(0\)表示......
  • 题解:Codeforces Round 961 (Div. 2) A
    A.Diagonals*timelimitpertest:1secondmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputVitaly503isgivenacheckeredboardwithasideof\(n\)and\(k\)chips.Herealizedthatallthese\(k\)chipsneedto......
  • [题解]CF958C3 Encryption (hard)
    思路先考虑\(\Theta(n^2k)\)的暴力DP。定义\(dp_{i,j}\)表示在前\(i\)个数中选取\(j\)个的最小和,转移显然:\[dp_{i,j}=\min_{1\leqk<i}\{dp_{k,j-1}+s_{k+1,i}\bmodp\}\]注意到一个性质:\(dp_{i,j}\equivs_i\pmodp\)。因为前者是前\(i\)项分为若干......
  • Java二叉树经典进阶OJ题解
     目录一、判断一颗二叉树是否为对称二叉树1.题目描述:2.代码示例:3.通过演示与分析:二、根据先序遍历结果构造二叉树1.题目描述:2.代码示例:3.通过演示与分析:三、层序遍历的非递归实现1.题目描述:2.代码示例:3.通过演示与分析:四、判断是否为完全二叉树1.题目描述:2.......
  • dify-on-wechat 数据乱串问题解决记录
    在检查dify-on-wechat应用中的数据乱串问题时,我们发现了一个关键因素:当前端和后端使用的大语言模型不一致时,会导致数据串扰问题。在深入调查和测试后,我们采取了将前后端的大语言模型改为一致的策略。在实施这一改变后,数据乱串的问题得到了有效解决。以下是详细的记录:问题现象:在dif......
  • 密码学-RSA基础题解题脚本-Python
    importgmpy2#计算大整数模块importlibnumimportrsafromCrypto.PublicKeyimportRSA#安装时安装pycryptodome模块#已知:p,q,e,cdefknown_p_q_e_c():p=int(input('请输入一个素数p:'))q=int(input('请输入另一个素数q:'))e=int(input('请输入公钥e:'))......
  • [题解]P9755 [CSP-S 2023] 种树
    P9755[CSP-S2023]种树迟来的补题本题是让最小化所有树长到指定高度日期的最大值,于是想到二分答案。那么,对于一个给定的期限\(x\),如何判断是否能在这个日期内完成任务呢?首先我们发现前\(n\)天每天都要种树,那么假设我们已经知道了每个地块最晚哪个日期种树,能保证在期限\(x\)......