2025/7/17 数据结构专题
2025/7/17 \(\mathbf{} \begin{Bmatrix} \frac{{\Large LEARN} }{{\color{Yellow}\Large Record} }\mathbf{} {No.9} \end{Bmatrix}\times{}\) NeeDna
| 题号 | 来源 | 知识点标签 | 难度(洛谷难度标记) | 一句话题解(尽量) | 备注(推荐理由,题目特点等等) | 
|---|---|---|---|---|---|
| P7603 | 洛谷 | 堆 | 省选/NOI− | 减半警报器板子 | 见套路 | 
| P7560 | 洛谷 | 扫描线 | 省选/NOI− | 消除离开不够,转化为扫描线板子 | 洛谷省选/NOI−题,扫描线应用,适合进阶训练 | 
| P9596 | 洛谷 | 线段树 | 省选/NOI− | 转化,线段树维护 | 洛谷省选/NOI−题,经典转化思路,线段树练手好题,适合进阶训练 | 
| loj2461 | LOJ | 分块 | 经典分块问题 | LOJ经典分块题,分块思想实践 | |
| P9968 | 洛谷 | 二进制 | 提高+/省选− | 二进制分组,暴力 | 洛谷提高+/省选−题,适合提高训练 | 
| gym 102331F | Codeforces | 堆 | 减半警报器板子 | 见套路 | |
| P4198 | 洛谷 | 线段树 | 省选/NOI− | 斜率单调栈维护 | 洛谷省选/NOI−题,斜率优化经典题,线段树练手好题,适合进阶训练 | 
| CF765F | Codeforces | 线段树 | NOI/NOI+/CTSC | 线段树维护区间信息 | Codeforces经典线段树题,线段树练手好题,适合进阶训练 | 
| P7561 | 洛谷 | 二分,扫描线 | 省选/NOI− | 扫描线处理 | 洛谷省选/NOI−题,扫描线应用,适合进阶训练 | 
| CF803G | Codeforces | 线段树,st 表 | 省选/NOI− | 线段树维护区间信息 | Codeforces经典线段树,st 表题,线段树练手好题,适合进阶训练 | 
| CF193D | Codeforces | 线段树 | 省选/NOI− | 线段树维护区间信息 | Codeforces经典线段树题,线段树练手好题,适合进阶训练 | 
| CF377D | Codeforces | 扫描线,线段树 | 省选/NOI− | 线段树维护区间信息 | Codeforces经典扫描线,线段树题,线段树练手好题,适合进阶训练 | 
| CF1677E | Codeforces | 扫描线 | 省选/NOI− | 扫描线处理 | Codeforces经典扫描线题,扫描线应用,适合进阶训练 | 
| CF1446D2 | Codeforces | 根号分治 | 省选/NOI− | 根号分治处理 | Codeforces经典根号分治题,根号分治典型,适合进阶训练 | 
| CF436F | Codeforces | 分块,斜率优化 | NOI/NOI+/CTSC | 分块处理 | Codeforces经典分块,斜率优化题,分块思想实践,适合进阶训练 | 
| UOJ812 | UOJ | 主席树 | 经典主席树问题 | UOJ经典主席树题 | |
| UOJ515 | UOJ | Seg Beats | 离线转化为 Seg Beats 板子 | 了解 Seg Beats | |
| CF671E | Codeforces | 线段树 | NOI/NOI+/CTSC | 线段树维护区间信息 | Codeforces经典线段树题,线段树练手好题,适合进阶训练 | 
| P4314 | 洛谷 | 历史最值 | 省选/NOI− | 历史最值标记处理 | 洛谷省选/NOI−题,历史最值处理模板,适合进阶训练 | 
| P2048 | 洛谷 | st 表 | 省选/NOI− | ST表+堆维护前k大 | 洛谷省选/NOI−题,ST表应用经典,适合进阶训练 | 
| CF1491H | Codeforces | 树分块 | NOI/NOI+/CTSC | 分块处理 | Codeforces经典树分块题,分块思想实践,适合进阶训练 | 
| P5355 | 洛谷 | 莫队,bitset | 省选/NOI− | 莫队+bitset维护 | 洛谷省选/NOI−题,bitset优化经典,莫队算法练习,适合进阶训练 | 
| UOJ671 | UOJ | 线段树 | 线段树维护区间信息 | UOJ经典线段树题,线段树练手好题 | |
| QOJ6630 | QOJ | 线段树 | 经典线段树问题 | QOJ经典线段树题,线段树练手好题 | |
| CF1270F | Codeforces | 根号分治 | 省选/NOI− | 根号分治处理 | Codeforces经典根号分治题,根号分治典型,适合进阶训练 | 
| UOJ169 | UOJ | 线段树 | 线段树维护区间信息 | UOJ经典线段树题,线段树练手好题 | |
| CF1580C | Codeforces | 根号分治 | 省选/NOI− | 根号分治处理 | Codeforces经典根号分治题,根号分治典型,适合进阶训练 | 
| P7708 | 洛谷 | 回滚莫队 | 省选/NOI− | 经典回滚莫队问题 | 洛谷省选/NOI−题,莫队算法练习,适合进阶训练 | 
| P4755 | 洛谷 | CDQ 分治,树状数组 | 省选/NOI− | 经典CDQ 分治,树状数组问题 | 洛谷省选/NOI−题,CDQ分治经典,适合进阶训练 | 
| P9062 | 洛谷 | 分块 | NOI/NOI+/CTSC | 分块处理 | 洛谷NOI/NOI+/CTSC题,分块思想实践,适合进阶训练 | 
| P3437 | 洛谷 | 树套树 | 提高+/省选− | 经典树套树问题 | 洛谷提高+/省选−题,适合提高训练 | 
| P4098 | 洛谷 | 主席树 | 省选/NOI− | 经典主席树问题 | 洛谷省选/NOI−题,适合进阶训练 | 
| P2839 | 洛谷 | 线段树 | 省选/NOI− | 线段树维护区间信息 | 洛谷省选/NOI−题,线段树练手好题,适合进阶训练 | 
| CF1051G | Codeforces | 线段树合并,并查集 | NOI/NOI+/CTSC | 线段树维护区间信息 | Codeforces经典线段树合并,并查集题,线段树练手好题,适合进阶训练 | 
| P3206 | 洛谷 | CDQ | 省选/NOI− | 经典CDQ问题 | 洛谷省选/NOI−题,CDQ分治经典,适合进阶训练 | 
| P7602 | 洛谷 | 树状数组 | 提高+/省选− | 经典树状数组问题 | 单 log 的套路可以积累 | 
| CF1172F | Codeforces | 线段树 | NOI/NOI+/CTSC | 线段树维护区间信息 | 经典线段树题,线段树练手好题,适合进阶训练 | 
| CF1340F | Codeforces | 线段树,分块 | NOI/NOI+/CTSC | 线段树维护区间信息 | Codeforces经典线段树,分块题,线段树练手好题,适合进阶训练 | 
| CF1098D | Codeforces | set | 省选/NOI− | set维护有序信息 | Codeforces经典set题,适合进阶训练 | 
| UOJ164 | UOJ | 线段树 | 线段树维护区间信息 | UOJ经典线段树题,线段树练手好题 | |
| P3658 | 洛谷 | CDQ,树状数组 | 省选/NOI− | CDQ分治处理 | 洛谷省选/NOI−题,CDQ分治经典,适合进阶训练 | 
| loj3282 | LOJ | 线段树,最短路 | 线段树维护区间信息 | LOJ经典线段树,最短路题,线段树练手好题 | |
| loj3038 | LOJ | 线段树 | 线段树维护区间信息 | LOJ经典线段树题,线段树练手好题 | |
| P4602 | 洛谷 | 整体二分,树状数组 | 省选/NOI− | 整体二分+树状数组 | 洛谷省选/NOI−题,整体二分应用,适合进阶训练 | 
| loj3030 | LOJ | 线段树,三位偏序 | 线段树维护区间信息 | LOJ经典线段树,三位偏序题,线段树练手好题 | 
P9968 [THUPC 2024 初赛] 二进制
题目描述
小 F 给出了一个这里有一个长为 \(n\) 的二进制串 \(s\),下标从 \(1\) 到 \(n\),且 \(\forall i\in[1,n],s_i\in \{0,1\}\),他想要删除若干二进制子串。
具体的,小 F 做出了 \(n\) 次尝试。
在第 \(i\in[1,n]\) 次尝试中,他会先写出正整数 \(i\) 的二进制串表示 \(t\)(无前导零,左侧为高位,例如 \(10\) 可以写为 \(1010\))。
随后找到这个二进制表示 \(t\) 在 \(s\) 中从左到右 第一次 出现的位置,并删除这个串。
注意,删除后左右部分的串会拼接在一起 形成一个新的串,请注意新串下标的改变。
若当前 \(t\) 不在 \(s\) 中存在,则小 F 对串 \(s\) 不作出改变。
你需要回答每一次尝试中,\(t\) 在 \(s\) 中第一次出现的位置的左端点以及 \(t\) 在 \(s\) 中出现了多少次。
定义两次出现不同当且仅当出现的位置的左端点不同。
做法
因为数字 \(n\) 最多有 \(\log n\) 位,所以我们把所有可能的答案都记下来,删除的时候标记偏移量,用桶存答案个数就可以了。\(O(n\log ^2 n)\)
CF803G Periodic RMQ Problem
题目描述
给你一个整数序列 \(a\),你要执行 \(q\) 次操作,分两种:
1 l r x:将 \(a_l\sim a_r\) 赋值为 \(x\)。2 l r:求 \(a_l\sim a_r\) 中的最小值。
我们认为这个问题太简单了,所以不直接给出 \(a\),而是给出长度为 \(n\) 的序列 \(b\),将 \(b\) 复制 \(k\) 份,拼在一起得到 \(a\)。
做法
动态开点线段树解决修改,对于查询线段树上没有的节点直 接在\(b_n\) 上查就行。
细节:在我们上面保留的点的基础上,相邻两个已经保留的点之间的最小值也是需要的(但不需要整段的信息,因为不会有询问只询问这一段的一半,或者是修改一半,不然这一段就会被分成两段甚至更多),所以在上面的基础之上,我们把相邻两个点之间的最小值也插入进去做线段树就没问题了。
所以空间要开 4 倍。
P7560 [JOISC 2021] フードコート (Day1) 没懂
题意
维护 \(n\) 个序列,\(m\) 次操作。每次在 \([l,\,r]\) 的序列末尾加 \(k\) 个数字 \(c\),或者在开头删去 \(k\) 个数字(如果 \(k\) 大于等于序列长度则删完),或者查询序列 \(a\) 的第 \(b\) 个位置的数字。
做法
- 
发现离开人数不够很麻烦,考虑将不够的人数加在询问上就 可以不管了。
 - 
现在问题变成区间加减,查寻第K 大,显然是扫描线板子。
 
P4198 楼房重建
题意
有 \(N\) 栋正在坐标轴上修建的楼房和 \(M\) 个时间节点,已知每个时间节点上会有一栋楼的高度发生变化。 问对于每个时间节点,小 A 在原点可以看到几栋楼房(基于日常生活理解)。
做法
• k递增才能看见考虑用线段树维护斜率最大值mx 和答案s。
• 如果改的是右儿子,就对左儿子没有影响。
• 如果改的是左儿子,就对右儿子的答案进行calc。如果 ki > mxlson,那对右儿子 calc,左儿子的 s 全赋成 0,反之 calc 左儿子。
P7603 [THUPC 2021] 鬼街 没听懂
P9596 [JOI Open 2018] 冒泡排序 2 没懂
题意
一个序列 \(A\) 的扫描次数为 \(\max_{i=1}^n \sum_{j=1}^i[a_j>a_i]\)。
证明
发现一次操作必定将恰好一个 \(p\) 前面大于他的数换到他后面(排除没有的)。原式子相当于对于每个位置 \(p\) ,把其前面大于他的换到他后面需要的扫描次数取 \(\max\) ,即操作后对于每个位置其前面没有大于他的,序列 \(A\) 就是拍好序列。
发现同样的值只有最后一个位置 \(p\) 有用,一种值的答案为 \(\sum [A_i>v]-(n-p)\),其中可以把 \(n-p\) 看作后面比他大的值,因为如果后面有比他小的值 \(v2\) ,他的最后一个位置 \(p2>p\),一定有 \(\sum [A_i>v2]-(n-p2)>\sum [A_i>v]-(n-p)\) ,即值 \(v\) 一定不优。
做法
开棵权值线段树直接维护这个式子的最值,权值线段树支持区间加,维护最大值即可。
P9247 [集训队互测 2018] 完美的队列 没懂
题意
有 \(n\) 个队列,容量为 \(a_i\)。\(m\) 次操作 \((l,r,x)\),向第 \([l,r]\) 个队列插入 \(x\),超出容量弹出队头。
求每次操作后全局颜色数量,\(n,m\le 10^5\)。
P7561 [JOISC 2021] 道路の建設案
题意
求前 $k $ 大的曼哈顿距离,先考虑求第 \(k\) 大的距离。
做法
第 \(k\) 大的距离,比较套路的做法是二分答案,然后计算距离 \(\le dis\) 的点对数。
曼哈顿距离不好求,考虑转化为切比雪夫距离,原来的点 \((x,y)\to (x+y,x-y)\) 。
那么这就是一个经典的二维数点问题。
同时我们不需要真正数有多少点对,点对数 \(\ge k\) 时直接返回即可。
所以具体操作是对所有点按 \(x\) 坐标排序,用队列维护 \(x\) 坐标在 \(dis\) 范围内的点,同时用 set 维护队列中的点的 \(y\) 坐标。
值域为 \(S\) ,则时间复杂度为 \(\mathcal{O}((n+k)\log n\log S+k\log k)\) 。
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=2.5e5+10;
struct Node {int x,y;}t[MAXN];
int n,k,cnt;
vector<int> ans;
multiset<pair<int,int>> st;
int check(int len) {
	ans.clear(),st.clear();
	int pos=1; cnt=0;
	ffor(i,1,n) {
		if(i-1) st.insert({t[i-1].y,i-1});
		while(t[i].x-t[pos].x>len) st.erase({t[pos].y,pos}),pos++;
		auto it=st.lower_bound({t[i].y-len,0});
		while(it!=st.end()&&it->first<=t[i].y+len) {
			cnt++,ans.push_back(max(abs(t[i].y-it->first),abs(t[i].x-t[it->second].x))),it++;
			if(cnt>k) return 0;
		}
	}
	return 1;
}
void bfind(int l,int r) {
	int aans=0;
	while(l<=r) {
		int mid=l+r>>1;
		if(check(mid)) aans=mid,l=mid+1;
		else r=mid-1;
	}
	check(aans);
	ffor(i,1,k-cnt) ans.push_back(aans+1);
	return ;
}
signed main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n>>k;
	ffor(i,1,n) {int x,y; cin>>x>>y,t[i]={x+y,x-y};}
	sort(t+1,t+n+1,[](Node A,Node B) {
		if(A.x!=B.x) return A.x<B.x;
		return A.y<B.y;	
	});
	bfind(1,4000000000);
	sort(ans.begin(),ans.end());
	for(auto v:ans) cout<<v<<'\n';
	return 0;
}
CF193D Two Segments 没懂
题意
给一个 \(1\sim n\) 的排列 \(a\),求有多少种选择两个不重叠的区间 \([l_1, r_1]\) 和 \([l_2,r_2]\) 的方法让这些元素排序之后在值域里是连续的一段。\(1\le n\le 3\times 10^5\)。
CF1677E Tokitsukaze and Beautiful Subsegments 没懂
题意
给定排列 \(\{p_n\}\),定义一个区间 \([l,r]\) 是好的,当且仅当存在 \(l \le i < j \le r\),满足 \(p_i\times p_j = \max\{p_l, p_{l + 1}, \dots, p_r\}\),\(q\) 次询问 \([l,r]\),求 \([l,r]\) 有多少个子区间是好的。\(n \le 2 \times 10^5, q \le 10^6\)

                
            
        
浙公网安备 33010602011771号