南外集训Day1
又要集训了,但是这次似乎是线上联训。我的这些博客里主要写自己的情况,比赛中一些有用的题会写题解,知识点讲座上基本的题都会讲大概做法。题解往往会采用吸星大法,提取课堂的精华来记录,大多时候会按照题目的套路来介绍。
分块
A. 最优贸易简化版
题面
C国有 $n$ 座城市,编号是 $1$ 到 $n$ ,编号为 $i$ 的城市有路到编号为 $i+1$ 的城市(编号为 $n$ 的城市没有路到其他的城市)。 C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。 商人阿龙再次来到C国旅游。他还是想贩卖水晶赚取旅费,在某个城市买入,再另一个城市卖出。 他将从编号为 $a$ 的城市到编号到 $b$ 的城市。请你帮他算算,最多能赚多少钱。 注:他最多进行一次买入和一次卖出。
思路
-
分块
处理每个块内的最大差价,以及块最小最大值,然后对于所有区间内的块扫一遍,求块内差价与多块的差价的最大值。
-
倍增
把块换成 $2^k$ 长度的段。
-
线段树
维护方法同上。
-
并查集
离线,按右端点排序,假设右端点为父亲,左端点去找父亲,路径上处理和前面的分块和倍增一样。
-
树上加强版
可以使用倍增维护一个节点到祖先的链,然后把一条路径分成两条,再合并。
青蛙跳
题面
$n$ 个点,每个点权值 $a_i$ ,弹跳值 $t$ ,如果青蛙在 $x$ 位置,起跳后会去 $t+x,x+2*t$ ,跳到再跳就超过 $n$ 为止,$m$ 个询问,给 $x,t$ ,求跳的权值总和。
思路
-
分块
分两种情况考虑,当 $t<=\sqrt n$ 的时候预处理,否则暴力跳。时间复杂度 $O(n \sqrt n)$。
预处理:$sum[i][j]=sum[i+j][j]+a[i]$,其中sum[i][j]为从 $i$ 开始跳,跳跃长度为 $j$ 的食物量,其中 $j<=\sqrt n$ 。
弹飞绵羊
题目。
题面
某天,Lostmonkey 发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。
游戏一开始,Lostmonkey 在地上沿着一条直线摆上 $n$ 个装置,每个装置设定初始弹力系数 $k_i$,当绵羊达到第 $i$ 个装置时,它会往后弹 $k_i$ 步,达到第 $i+k_i$ 个装置,若不存在第 $i+k_i$ 个装置,则绵羊被弹飞。
绵羊想知道当它从第 $i$ 个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey 可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
思路
-
分块
处理出每个块内跳几次跳出这个块,块内由后向前处理。
修改的话只会对块内他前面的值(即几次跳出块)进行修改 。
蒲公英
题目。
题面
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为 $n$ 的序列 $\{a_1,a_2..a_n\}$,其中 $a_i$ 为一个正整数,表示第 $i$ 棵蒲公英的种类编号。
而每次询问一个区间 $[l, r]$,你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
注意,你的算法必须是在线的。
思路
-
分块
分块后,众数只可能在下面两个部分:
- 中间完整快的众数。
- 两端不完整块中的每个数字。
预处理出:
- $v[i][j]$ 块i到块j的众数
- $cnt[i][j]$ 表示数值i在前j块中出现的次数,注意要对数值离散化
然后对于每次询问对于每个区间中间直接处理,两端暴力,然后根据出现次数直接比较。
动态逆序对
题目。
题面
对于序列 $A$ ,它的逆序对数定义为满足 $i<j$ ,且 $A_i>A_j$ 的数对 $(i,j)$ 的个数。给定 $1$ 到 $n$ 的一个排列,按照某种顺序依次删除 $m$ 个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
思路
-
树套树
非常简单,删除时把少掉的逆序对剪掉,然后乱糊一棵树套树即可水过。
因为考虑第一维的空间不大,但第二维有很多空间是多余的(要用线段树动态开点),所以可以树状数组套线段树。
-
分块套树状数组
直接分块,块里权值树状数组,减掉逆序对的思维同于树套数。
动态最大连续和
题目。
题意
单点修改,区间查询最大子段和。
思路
不难发现,这道题即带修最大子段和问题。
-
线段树
线段树上维护每个区间最大前缀,最大后缀以及最大子段和。
最大子段和等于左区间的最大后缀加有区间的最大前缀与左右区间的最大子段和的最大值。
区间元素平方和
题意
区间加数,区间查询数的平方之和。
思路
-
线段树
利用完全平方公式,所以维护区间和与区间平方和即可轻松水过。就是区间减数也同理。
子序列问题
题意
求所有区间的不同元素个数的平方之和。
思路
-
线段树
我们考虑扫描线,从左往右扫,扫到的是右端点,我们考虑能对集合大小产生贡献的也就是 $last_{a_i}+1$ 到 $i$ 这段区间,贡献为 $1$ ,其中 $last_a_i$ 表示值等于 $a_i$ 的上一个位置。那么这个问题也就转换成了上一个问题。
永无乡
题目。
题意
给定一些点,每个点有权值,初始有一些边。有 $q$ 次操作,每种操作有两类
- $x$ 与 $y$ 建立无向边
- 求所有与 $x$ 联通的点里,输出第 $k$ 小。
思路
-
线段树合并
集合用一颗线段树表示,线段树合并(线段树为权值线段树)。初始每个节点一棵大小 $logn$ 的线段树。
线段树合并的过程即如果两颗要合并的线段树中只有一颗线段树有当前位置,那么就只用一颗,否则合并,继续递归。
时间复杂度: $O(nlogn)$ ,我们考虑证明:我们发现,会往下递归当且仅当两颗线段树的当前位置都有节点,那么合并后必定少一个,所以我们发现递归了多少次就删除多少个节点(递归的最后一层除外)。那么因为节点数总共就是 $nlogn$ 的,所以时间复杂度也不言而喻了。
[POI2011]XOR Tree Rotations
题目。
题意
给定一颗二叉树,每个叶节点有权值,权值为 $1$ 到 $n$ 的排列,可以任意交换每个非叶子节点的左右儿子,使得最终按顺序得到的叶节点序列的逆序对数最少。
思路
-
线段是合并
考虑节点 $x$ 有两颗子树 $a,b$ ,他们交换不会影响 $a,b$ 子树内的答案。
那么 $dfs$ 遍历到叶节点,每个叶节点维护一颗权值线段树,然后每上去一个节点就线段树合并,合并时发现逆序对的个数就是每一步左边子树的右区间,乘上右边子树的左区间,如果发现交换能使答案变小,那就交换。
祝下午切水题顺利!