首页 > 其他分享 >数据结构随记

数据结构随记

时间:2023-09-13 09:24:00浏览次数:35  
标签:leftarrow sum 区间 ge forall 操作 数据结构 随记

单调栈

CF671E Organizing a Race

记 \(a_i = \sum_{j = 1}^{i - 1} g_j - \sum_{j = 1}^{i - 1} w_j,\, b_i = \sum_{j = i + 1}^n g_j - \sum_{j = i}^{n - 1} w_j\),则区间 \([l, r]\) 合法的充要条件为 \(\forall i \in [l, r], a_i \ge a_l \land b_i \ge b_r\)。

当 \(g_i \leftarrow g_i + 1\) 时,\(\forall j \in [i + 1, n], a_j \leftarrow a_j + 1,\, \forall j \in [1, i - 1], b_j \leftarrow b_j + 1\)。

我们固定区间 \([l, r]\),试判断这个区间是否能在 \(k\) 次操作内变得合法。

首先我们需要满足 \(a_i\) 的限制。不难发现我们只需要关注 \([l, r]\) 内 \(a_i\) 的严格前缀最小值,记它们的下标为 \(p_1 < p_2 < \dots < p_k\)。我们会让每个操作位置尽可能靠右,这样更有利于满足 \(b_i\) 的限制。因此我们的操作可以表示为 \(\forall i \in [2, k], g_{p_i - 1} \leftarrow g_{p_i - 1} + a_{p_{i - 1}} - a_{p_i}\)。

记经过上述操作后 \(b_i\) 变为 \(b^{\prime}_i\)。剩余的 \(k - a_l + a_{p_k}\) 次操作一定在 \(r\) 处使用最优,即我们合法的充要条件为 \(\forall i \in [l, r], b^{\prime}_i \ge b_r - k + a_l - a_{p_k}\)。

考虑从 \(n\) 到 \(1\) 枚举 \(l\),用单调栈维护 \([l, n]\) 内 \(a_i\) 的严格前缀最小值下标 \(q_1 < q_2 < \dots < q_m\)。同时,用线段树维护出经过区间 \([l, n]\) 的上述操作后 \(b_i\) 的值 \(t_i\)。

不妨先二分找到最小的 \(q_{x}\) 满足 \(a_l - a_{q_x} > k\)。当且仅当 \(r \le q_x - 1\) 时,区间 \([l, r]\) 能在 \(\le k\) 次操作中满足 \(a_i\) 的限制。

考察区间 \([l, r]\),我们此时维护的 \(t_i\) 是经过区间 \([l, n]\) 的操作后,而非经过区间 \([l, r]\) 的操作后的 \(b_i\)。由于我们只关心 \(b_i\) 的相对大小,不妨把 \(g_i \leftarrow g_i + 1\) 对 \(b_i\) 的影响改为 \(\forall j \in [i, n], b_j \leftarrow b_j - 1\)。这样,我们维护的 \(t_i\) 在 \(i \in [l, r - 1]\) 时就确实是经过区间 \([l, r]\) 的操作后的 \(b_i\)。区间 \([l, r]\) 合法的充要条件也改为 \(r < q_{x} \land \forall i \in [l, r - 1], t_i \ge b_r - k\)。

不难发现我们可以判断是否有 \(r \in [s, t]\) 使得区间 \([l, r]\) 合法。具体地,只需要判断 \(\min_{i \in [l, s - 1]} t_i \ge \min_{i \in [s, t]} b_i - k\)。这是因为 \(t_i \ge b_i - k\),因此 \([s, t]\) 中的最小值 \(b_p\) 一定满足 \(\min_{i \in [s, p - 1]} t_i \ge b_p - k\),因此只需要判断上述式子是否成立。

找出 \(q_x\) 后,可以在线段树上提取出区间 \([l, q_x - 1]\),然后线段树上二分即可找到最长的合法 \([l, r]\)。

时间复杂度 \(O(n \log n)\)。

提交记录

标签:leftarrow,sum,区间,ge,forall,操作,数据结构,随记
From: https://www.cnblogs.com/JCY-std/p/17698591.html

相关文章

  • 修改酒店索引库的数据结构
             ......
  • 数据结构——栈
    一、用数组实现栈的功能#include<iostream>//用数组实现栈的功能usingnamespacestd;#defineMAX_SIZE101//定义此栈最大空间为101intA[MAX_SIZE];inttop=-1;//定义全局变量top表示栈顶,当栈为空时,top=-1voidPush(intx){//压栈操作 if(top==MAX_SIZE-1){ c......
  • Redis五种数据类型及其数据结构
    Redis五种数据类型String数据结构:SDS应用类型:缓存数据,计数,互斥锁List数据结构:压缩列表或者双向链表应用类型:缓存链表或者作为队列Hash数据结构:压缩列表或者哈希表应用类型:缓存对象Set数据结构:整型集合或者哈希表应用类型:缓存集合,例如好友关系Zset......
  • 《Hello算法》笔记2数据结构
    逻辑结构逻辑结构揭示了数据元素之间的逻辑关系。线性数据结构:数组、链表、栈、队列、哈希表。非线性数据结构:树、堆、图、哈希表。 线性结构:数组、链表、队列、栈、哈希表,元素之间是一对一的顺序关系。树形结构:树、堆、哈希表,元素之间是一对多的关系。网状结构:图,元素......
  • 数据结构之链表
    说明链表是数据结构中的线性结构,用于存储一系列元素(节点),其中每个元素都包含一个指向下一个元素的引用。链表由一组节点组成,每个节点包含两个部分:数据和指向下一个节点的指针(或引用)。线性结构中对比数组/列表的优势:插入和删除性能较好涉及的概念:1.节点:节点包括2个域,元素域、......
  • 一道数据结构
    题意:给定长度为\(n\)的序列\(a\),\(m\)次询问,每次询问区间\([l,r]\)中选取三个点\(i,j,k\)满足\(l\lei<j<k\ler\)且\(j-i\lek-j\),你需要使得\(a_i+a_j+a_k\)最大,输出这个最大值。数据范围:\(3\len\le5\times10^4\),\(1\lea_i\le10^9\),\(1\lem\le5\times1......
  • hotel数据结构分析
           ......
  • 一种高效且节约内存的聚合数据结构的实现
    一种高效且节约内存的聚合数据结构的实现在特定的场景中,特殊定制数据结构能够得到更加好的性能且更节约内存。聚合函数GroupArray的问题GroupArray聚合函数是将分组内容组成一个个数组,例如下面的例子:SELECTgroupArray(concat('ABC-',toString(number)))fromnumbers(20)gr......
  • 数据结构思维导图
    思维导图......
  • C数据结构-线性表之顺序表
    什么是线性表线性表的插入元素线性表的删除元素线性表顺序存储的缺点线性表的特点1.线性表的实例首先我们创建3个文件,分别如下:liner_data--sqlist.c--sqlist.h--test.csqlist.h//.h文件中定位数据的结构以及函数的方法typedefintdata_t;#defineN128......