模拟赛

第一套题目

Game

时间限制: 1s 空间限制: 1024MB 文件名称: Game.in/Game.out

题目描述

灵梦和早苗的班级要进行一次长跑接力比赛。灵梦的班级有n个选手,早苗的班级有 \(m\) 个选手。每个选手拥有两个属性,能力值 \(w_i\) 和精彩度 \(v_i\) (精彩度可能为负数)。

两队要分别选出若干选手进行比赛,为了公平起见,两队选手的能力值之和需要相等。我们称一场比赛的精彩度为两队所有参加比赛的选手的精彩度总和。灵梦和早苗希望能够找到一种组队的方式,在保证公平的情况下,比赛尽可能精彩。

你需要求出这个最大的精彩度并将其输出,特别的,如果无论如何组队精彩度都会小于 \(0\) ,输出 \(0\) 。保证至少存在一种合法的组队方案。

输入格式

第一行包含两个正整数 \(n,m\) ,表示两个队伍的人数。

接下来 \(n\) 行,每行两个整数 \(w_i,v_i\) ,表示灵梦班级第 \(i\) 个人的属性。

接下来 \(m\) 行,每行两个整数 \(w_i,v_i\) ,表示早苗班级第 \(i\) 个人的属性。

输出格式

一行一个整数,表示所求的答案。

样例输入1

3 4
4 7
3 8
2 2
1 4
5 8
1 3
4 4

样例输出1

30

样例解释1

选择第一个队伍里的第 \(1,2\) 个选手,第二个队伍里第 \(1,2,3\) 个选手,此时两个队伍能力值之和都为 \(7\) ,精彩度总和为 \(30\) ,是最优的方案。

样例输入2

1 2
1000 -10000
200 3000
800 5000

样例输出2

0

样例解释2

无论如何都无法在公平的前提下使精彩度 \(≥0\) ,所以输出 \(0\)

数据范围及约定

对于 \(30\%\) 的数据:\(n,m≤50\)

对于另 \(40\%\) 的数据:\(|v|≤10000\)

对于所有数据:\(n,m≤1000,1≤w_i≤1000,|v|≤10^9\)

Dig

时间限制: 2s 空间限制: 512MB 文件名称: Dig.in/Dig.out

题目描述

铃仙被抓进了月都里带领兔子们挖矿。

月都的矿场有\(n\)层节点可供挖矿,第\(i\)层有\(i\)个节点(从\(1\)开始编号),第一层是地面且只有一个节点。每个节点有一个收益(收益可能为负数),保证地面上的节点的收益为\(0\)。一个节点可以通向它左下或右下的节点,也就是说第\(x\)层第\(y\)个节点可以通向第\(x+1\)层第\(y\)个节点和第\(x+1\)层第\(y+1\)个节点。

兔子们可以在一些节点建设基地,初始只有地面上的节点是基地。每一天兔子们可以向成为基地的节点的左下或右下方挖若干个节点,获得收益后这些节点将在第二天变为基地。

注意一个基地可以同时向左下和右下方挖,也可以不向任何一个方向挖。

多个基地可以在同一天中同时挖矿,唯一的要求是一个基地向某个方向挖矿时不可以中途改变方向

一个节点只能恰好被挖掘一次,被挖掘过的节点不可被再次挖掘,所以向某个方向挖掘时无法穿过被挖掘过的节点。

注意一天之内也无法挖掘同一个节点两次。

兔子们想知道\(K\)天之内可以获得的最大收益是多少。

输入格式

本题有多组测试。第一行一个整数\(T\)表示测试个数。接下来每个测试点:

第一行两个整数\(n\)\(K\)

接下来\(n-1\)行,第\(i\)行有\(i+1\)个整数,表示第\(i+1\)层每个节点的收益。

输出格式

每个测试点输出一行一个整数表示答案。

样例输入

6
2 1
1 1

4 2
  1 -9
-9 1 -9
1 1 1 -9

4 2
  1 -9
 1 1 -9
1 1 1 -9

4 2
   1 1
 -9 1 -9
-9 1 1 -9

3 1
     1000000000 1000000000
1000000000 1000000000 1000000000

2 1
-1 -1

样例输出

2
3
6
4
4000000000
0

样例输入为了拥有更好的视觉效果所以可能与最终测试数据格式稍有不同。

数据规模与约定

\(10\%\)的数据保证\(n \le 2\)

\(20\%\)的数据保证\(n \le 3\)

另外\(10\%\)的数据保证\(K = 1\)

\(50\%\)的数据保证\(n \le 10\)

\(70\%\)的数据保证\(n \le 15\)

\(100\%\)的数据保证\(T \le 50\), \(2 \le n \le 50\), \(1 \le K \le 2\) 权值的绝对值不超过\(10^9\)

Unreal

时间限制: 1s 空间限制: 1024MB 文件名称: Unreal.in/Unreal.out

题目描述

灵梦最近在社交平台上发表了一张自己的自拍照片。为了让自己显得更好看,她将照片进行了编辑。但灵梦是一个PS初学者,她非常糟糕地将 \(n\) 个时钟留在了图片里,这些钟表在PS后表盘出现了歪曲,显示出了不正常的时间。但非常巧合的是,所有时钟显示出的时间仍然是真实存在的时间,第 \(i\) 个时钟的样子正好是\(h_i:m_i:s_i\) (分别代表时、分、秒)的时候的一个正常时钟,虽然时间可以精确到秒,不过所有时钟上只有时针和分针

早苗只看了照片一眼,就发现了灵梦的照片是经过修改的。不过早苗突然非常好奇,灵梦拍下这张照片时,最可能是什么时间。为了得到答案,早苗定义了某个时间与照片的误差:

某时间与照片的误差定义为,在这个时间里,真实的钟表的时针与分针,分别与照片中的 \(n\) 个钟表的时针与分针的角度差异的最大值。

例如:假设照片上有 \(12:00:00\)\(2:00:00\) 两个钟表,那么时间 \(1:00:00\) 与照片的误差是 \(30°\) ,因为此时的时针与两个钟表的时针角度差异都是 \(30°\) ,而分针与两个钟表的分针角度差异都是 \(0\)

早苗已经在心中推理出了最可能的拍摄时间,他想请你告诉他一天中所有时间与照片误差的最小值,以此验证他的推理是否正确。

输入格式

第一行一个整数 \(n\) 表示照片里的钟表数量。

接下来 \(n\) 行,每行形如整数 \(h_i:m_i:s_i\) ,表示第 \(i\) 个钟表的时刻。保证 \(h_i,m_i,s_i\) 都是两位正整数(可能含有前导 \(0\) )且一定是一个从 \(00:00:00\)\(23:59:59\) 的合法时间。

输出格式

一行,一个浮点数,表示最小误差值,若你输出了 \(x\) ,则表示答案是 \(x°\)

若你的答案与标准答案相差不超过 \(10^{-5}\) 即视为答案正确。

样例输入1

2
12:30:00
02:40:00

样例输出1

32.5

样例解释1

当时间为 \(01:35:00\) 时,角度误差达到最小,此时最大的误差来源是两根时针,均相差了 \(32.5°\)

样例输入2

3
00:00:00
23:59:59
06:30:30

样例输出2

91.55

数据范围及约定

对于 \(10\%\) 的数据:\(n=2\)\(s_i=0\)

对于 \(40\%\) 的数据:\(n≤200\) 且所有 \(s_i=0\)

对于另 \(20\%\) 的数据:对于任意 \(i,j\) 都满足 \(h_i=h_j\) 且保证所有 \(m_i<30\)

对于所有数据:\(n≤50000\)

Tree

时间限制: 2s 空间限制: 1024MB 文件名称: Tree.in/Tree.out

题目描述

灵梦和早苗曾经有一张有标号带权无向完全图,边权都是 \(1,\frac{n(n-1)}{2}\) 之间的整数,且彼此互不相同。这张图保存了他们许多珍贵的记忆,然而时过境迁,物是人非,如今图已经消逝,而两人也已失散,只剩下残缺的回忆与无限的遗憾。

灵梦的记忆只剩下一些碎片,它们是 \(n-1\) 个互不相同的在 \(1,\frac{n(n-1)}{2}\) 之间的数字,是原图的最小生成树上所有边的权值。

她想通过这些记忆,还原出这张图。因此,她想知道有多少个不同的可能的图,满足这样的限制。两个图不同,当且仅当存在点对 \((u,v)\) 满足 \(u,v\) 之间的边权在两张图中不同。由于结果可能太大,请输出答案对 \(1000000007\) 取模的结果。

输入格式

第一行一个正整数 \(n\) ,表示图中的点数。

接下来 \(n-1\) 行,每行一个整数 \(a_i\) ,表示最小生成树的某条边的边权,保证 \(a_i\) 互不相同,且都是在 \(1,\frac{n(n-1)}{2}\) 之间的整数,保证按从小到大的顺序输入。

输出格式

一行一个整数,表示所求的答案对 \(1000000007\) 取模的结果。

样例输入1

3
1
2

样例输出1

6

样例解释1

容易发现任何一个图都满足限制,所以总方案是图的数量 \(6\)

样例输入1

5
2
3
4
5

样例输出1

0

数据范围及约定

对于 \(10\%\) 的数据:\(n≤5\)

对于 \(30\%\) 的数据:\(n≤7\)

对于 \(50\%\) 的数据:\(n≤15\)

对于 \(70\%\) 的数据:\(n≤30\)

对于另 \(20\%\) 的数据:\(a_i≤n\)

对于所有数据:\(n≤40\)

第一套题解

\(T1\ Game\)

算法 \(1:\ 30pts\)

\(n,m\leq 50\)

把第二个班的人看成负容量,只要求最终容量为\(0\)的最大权值,简单的\(01\)背包。

算法 \(2:\ 40pts\)

\(|v_i|\leq 10000\)

防止没开\(long\ long\)的小倒霉蛋爆掉,如果有根据这个性质得来的解法一定请讲讲\(XD\)

算法 \(3:\ 100pts\)

原题范围

大水题,沿用算法\(1\)的做法,中途舍弃过大的状态(因为在随机情况下,中途重新偏回来恰好为\(0\)的概率很小),为了强行制造随机情况,防止被精心构造的数据\(hack\)掉,\(random\_shuffle\)一下即可。

\(T2\ Dig\)

算法 \(1:\ 30pts\)

\(n\leq 3\)

随意爆搜即可。

算法 \(2:\ 40pts\)

\(k\leq 1\)

显然只能往左下,右下各挖一条且不会相交,结合算法1可以获得 \(40 pts\)

算法 \(3:100pts\)

考虑先 \(O(n^2)\) 枚举第一天的结果。那么第二天的结果一定是在第一天左下的路径上往右下挖,右下的路径上往左下挖。

\(S\) 为第二天所有从左边挖的点,定义左轮廓为满足从这个点开始一直往右上走能走到的第一个被挖的点属于 \(S\) 的点集,那么不交的条件可以转化为第二天从右边挖的点碰不到左轮廓的点。这样直接对左轮廓dp即可,只需要 注意正确统计贡献。

可能需要预处理从某个最左/右边的点往右下走的最大前缀和。

\(T3\ Unreal\)

算法 \(1:\ 10pts\)

\(n= 2,s_i=0\)

怎么暴力都可以。

算法 \(2:\ 40pts\)

\(n\leq 200,s_i=0\)

由于\(n\)比较小,而且\(s_i=0\),所以猜测可能可以枚举一些时刻暴力计算答案。但是枚举的精度显然应该要比秒还要小很多,暂时没有想到比较能够接受的算法,希望有会的同学可以分享一下。

算法 \(3:\ 20pts\)

\(h_i=h_j,m_i<30\)

由于小时数相同,并且分针全都在表盘的前半圈,那么很显然时针的差异无论如何不会超过分针的差异,那么只需要最小化分针的差异即可。容易发现,最优情况一定是选择最小分针角度和最大分针角度的等分点。

算法 \(4:\ 100pts\)

原题数据范围

要求最小化最大误差,很容易想到二分答案。那么我们二分答案后,只需要判定是否存在某个时间满足误差小于二分的答案即可。不妨设二分的答案为\(x\),对于每个指针,向前\(x^\circ\)一直到向后\(x^\circ\)的区间内都是合法的。

于是我们可以对时针和分针分别求出\(n\)个钟表的合法区间交集,若某种指针为空集,则肯定无解;否则,我们就可以得到时针和分针各自的范围。

如果时针的范围超过\(1h\),那么任意一个分针都是合法的,此时必定有解;如果时针的范围不到\(1h\),那么可以用时针范围直接计算出可被允许的分针范围,再与之前求出的分针范围求交集,若有交则有解,否则无解。

\(T4\ Tree\)

算法 \(1:\ 10pts\)

\(n\leq 5\)

大暴力,怎么写都可以。

算法 \(2:\ 30pts\)

\(n\leq 7\)

有点优化的大暴力。

算法 \(3:\ 50pts\)

\(n\leq 15\)

考虑\(DP\)\(f[i][s]\)表示当前考虑了前\(i\)短的边,联通状态为\(s\)的方案数,\(s\)的表示方法可以使用最小表示法之类的,状态转移只需要考虑下一条边连接了哪些点即可。

算法 \(4:\ 70pts\)

\(n\leq 30\)

如果正解常数不够优秀,超时后的保底分数。事实上也可能被非常优秀的大暴力们水过去。

算法 \(5:\ 20pts\)

\(a_i\leq n\)

有用的边只剩下前\(n\)条,假设\(x\)这条边不存在最小生成树里,那么必然是使得前\(x-1\)条边形成的生成树上出现了环,枚举环长后组合数学随便算算即可。

算法\(6:\ 100pts\)

原题数据范围

考虑优化算法\(3\),并不需要表示出具体的连通关系,只需要知道连通块的大小即可。于是方案数变成了\(40\)的整数分拆数,只有\(P(40)=37338\),枚举时也只需要枚举连通块大小而不需要枚举具体是哪个连通块,显然不同大小的连通块只会有\(\sqrt n\)个,枚举两个连通块复杂度是\(O(n)\)的。而需要进行枚举的转移也只有\(n-1\)次(只有\(n-1\)条有效边),其余根本不需要转移。所以最终复杂度是\(O(n^2P(n))\)的。

第二套题目

Sticky

时间限制: 1s 空间限制: 1024MB 文件名称: Sticky.in/Sticky.out

题目描述

桃井正在开发一款名为《贴贴世界》的游戏。

这款游戏中的关卡里有一个长为 \(L\) ,从 \(1\)\(L\) 编号的格子平台,里面有若干只名为黏块的生物,这些怪物在平台上可以看作一条线段,一开始,它们是分开且不重叠的。

桃井在平台上设置了 \(M\) 个发光格子,它希望玩家的目标是尽可能多的用黏块盖住这些发光格子。

平台很滑,所以玩家可以把这些黏块推来推去,具体的说,每次操作是这样的:

选择一个黏块,并把它向左或向右滑动。如果滑出边界,则它会掉落;如果碰到另一个黏块,则这两个黏块会融合成一个更长的黏块,并停留在原地。

现在,请你帮桃井计算一下,经过若干次操作后,最终最多能使这些黏块盖住多少个发光格子。

输入格式

第一行三个整数 \(N,M,L\)

接下来一行 \(N\) 个互不相同的正整数,描述 \(N\) 个有黏块的格子,每组连续的有黏块的格子代表一只黏块。

接下来一行 \(M\) 个互不相同的正整数,描述 \(M\) 个发光格子。

输出格式

一行一个正整数,表示最多能盖住多少个发光格子。

样例输入

10 10 20
16 2 7 1 8 15 6 20 10 9
7 6 1 15 5 14 17 19 4 18

样例输出

7

样例解释

\(6\)\(10\) 格的黏块向左推,将 \(15\)\(16\) 格的黏块向右推,最终可以盖住 \(1,4,5,6,7,18,19\) 号的发光格子。

数据范围及约定

对于 \(20\%\) 的数据:\(N,M,L≤20\)

对于 \(40\%\) 的数据:\(N,M,L≤100\)

对于 \(60\%\) 的数据:\(N≤1000\)

对于所有数据:\(N≤100000,M≤2000,L≤200000\)

Rhythm

时间限制: 1s 空间限制: 1024MB 文件名称: Rhythm.in/Rhythm.out

题目描述

桃井正在开发一款名为《节奏洞穴》的游戏。

每个关卡的地图是一个 \(N\)\(M\) 列的棋盘,桃井控制的角色第 \(0\) 秒时出生在 \(S\) 点,将要去往 \(T\) 点,但是在过程中,还需要收集 \(C\) 枚金币。

\(i\)\(j\) 列的格子每过 \(a_{ij}\) 秒都会生成一枚金币,换句话说,如果桃井控制的角色第 \(t\) 秒在 \((i,j)\) 上,并且 \(a_{ij} | t(t\neq 0)\) ,那么桃井就会获得一枚金币。

每秒桃井控制的角色可以往上,下,左,右中的一个方向移动一格的距离,也可以停留在原地不动。

现在桃井准备给每个关卡设置一个排行榜,但为了反作弊,桃井准备把所有比理论时间更快的账号直接封禁,于是她来求助你能不能帮她求出通过每一关的理论时间。

输入格式

第一行三个整数 \(N,M,C\)

接下来 \(N\) 行,每一行 \(M\) 个整数 \(a_{ij}\)

接下来一行四个整数 \(S_x,S_y,T_x,T_y\) ,表示 \(S\) 点和 \(T\) 点的坐标。

输出格式

输出一个整数,代表收集至少 \(C\) 枚金币且到达 \(T\) 点所花费时间的最小值。

样例输入

2 3 6
1 4 5
2 3 6
1 1 2 3

样例输出

6

数据范围及约定

对于 \(20\%\) 的数据:\(N,M≤4,C≤100\)

对于 \(30\%\) 的数据:\(C≤100\)

对于另 \(10\%\) 的数据:\(a_{ij}≤2\)

对于所有数据:\(1≤S_x,T_x≤N,1≤S_y,T_y≤M,N,M≤10,C≤10^{18},a_{ij}≤10\)

Maimai

时间限制: 1s 空间限制: 1024MB 文件名称: Maimai.in/Maimai.out

题目描述

桃井正在开发一款名为《歌萌DX》的游戏。

这款游戏中的每个谱面会在屏幕上显示 \(n\) 个点,一些点之间会由双向的星星\(slide\)连通起来,玩家要做的是划掉其中若干条星星,把这些点不重复且不遗漏的分成两个集合,使两个集合间的点互不连通,但每个集合内的点互相之间是连通的。

每条星星有一个分数 \(z\) ,如果一条被划掉的星星的两个端点在不同集合中,那么就可以获得这条星星的分数,如果划掉多条可以得分的星星,那么总分 \(T\) 为这些星星分数的异或和。

现在桃井突然想知道对于一个固定的谱面,所有可能的总分的和是多少?

由于这个数很大,所以只需要输出答案的前 \(9\) 位,如果不满 \(9\) 位则全部输出。

输入格式

第一行两个整数 \(n,m\) 代表点的个数和星星的个数。

接下来 \(m\) 行,每一行 \(3\) 个整数 \(x,y,z\) ,分别表示每条星星的两个端点和分数,点的编号从 \(1\)\(n\)

输出格式

输出一个整数,代表答案。

样例输入

3 2
1 2 3
2 3 3

样例输出

3

数据范围及约定

对于 \(20\%\) 的数据:\(n≤20,m≤400\)

对于另 \(20\%\) 的数据:\(m=n-1\) ,保证图是一棵树。

对于另 \(20\%\) 的数据:\(z≤16\)

对于所有数据:\(1≤n≤10^5,1≤m≤2*10^5,z≤10^9\) ,保证图没有重边和自环。

Portal

时间限制: 1s 空间限制: 1024MB 文件名称: Portal.in/Portal.out

题目背景

桃井正在开发一款名为《折跃门》的游戏。

这款游戏中的关卡里有一些地板和一些桥,地板分为红蓝两色,游戏的目标是从一块地板走到另一块地板,再走回来,并且保证两次踩过的地板颜色顺序相同。

但是这样的条件太过苛刻,于是桃井给主角提供了一把折跃枪,可以在出发前任意次交换任意两块地板的颜色。

现在桃井准备开始设计关卡,但她并不知道哪些关卡是有解的,所以她来请求你帮帮忙。

题目描述

有一棵 \(n\) 个节点的树,每个节点上写着 \(0\)\(1\)

\(m\) 次询问,每次询问会给定 \(u,v\) ,显然从 \(u\)\(v\) 存在唯一的最短路径。询问是否可以在任意次交换路径上的任意两个点的数之后,使路径上的数形成的 \(01\) 串是回文串。

如果可以形成回文串,那么进行这些操作,然后输出 \(Yes\) ,如果有多种构成回文串的方式,请构成字典序最小的那个回文串。注意,进行这些操作会对之后的询问产生影响。

如果不能形成回文串,那么输出 \(No\)

输入格式

第一行两个整数 \(n,m\) ,代表节点数和询问次数。

接下来一行一个长度为 \(n\)\(01\) 串,第 \(i\) 位表示编号为 \(i\) 的节点的初始数字。

接下来 \(n-1\) 行每行两个数 \(x_i,y_i\) ,表示一条边。

接下来 \(m\) 行每行两个数 \(u_i,v_i\) ,表示第 \(i\) 次询问的内容。

输出格式

输出 \(m\) 行,每行输出字符串 \(Yes\)\(No\) 表示是否能形成回文串。

样例输入

5 5
00100
1 2
1 3
3 4
1 5
4 4
1 3
4 3
5 1
4 2

样例输出

Yes
No
No
Yes
No

数据范围及约定

对于 \(20\%\) 的数据:\(n,m≤1000\) ,保证树的形态是一条链。

对于 \(40\%\) 的数据:\(n,m≤1000\)

对于另 \(20\%\) 的数据:\(n,m≤10^5\) ,保证树的形态是一条链。

对于所有数据:\(1≤n,m≤10^5,1≤x_i,y_i,u_i,v_i≤n\)

第二套题解

暂无

第三套题目

暂无

第三套题解

A - drone 题解

考察知识点

  • 简单数论
  • 观察

Subtask1 (20pts)

依据题意,暴力模拟即可。

时间复杂度 \(O(nMax(A_i))\)

Subtask2 (50pts)

在该数据范围下直接暴力不再可行。

我们考虑当只有两个数 \(a, b\) 的情况,容易观察出每次会将 \((a, b)\) 变为 \((a-b, b)\)

这种形式恰与求 \(gcd\) 的过程等价。

也就是每次操作并不会改变被操作数的 \(gcd\)

那么我们有 \(gcd(a_1, a_2, ..., a_n) = gcd(ans, ans, ..., ans) = ans\)

因此所求答案即为所有数的 \(gcd\)

Sol (100pts)

在多个维度情况下,容易观察到每个维度的操作是独立的。

因此只需要对每个维度套用 \(Subtask 2\) 的做法即可通过此题。

时间复杂度 \(O(n + log(max(A_i)))\)

总结

本题考查了简单数论如最大公约数的相关知识,对于 \(NOIP\) 级别的选手需要培养一些观察力。

期望均分:\(AC\)

B - charge 题解

考察内容

  • 图论
  • Dijkstra
  • 实数基础

Subtask1(20-30pts)

暴力枚举航线顺序;根据剪枝或乱搞能力优劣得分不等。

Subtask2(40pts)

\(a=b=c=0\) 时,原问题等价于一个简单的最短路。

直接使用 \(Dijkstra\) 即可。

Sol(100pts)

由于 \(N\) 较小,我们可以先计算出全部 \(N^2\) 个距离后转化为纯图论问题。

对于每次行走所需要耗费的时间为

\[a+b+c*T+d*dis(i,j) \]

其中充电时间 \(T\)

\[dis(i,j) + 前往最近充电桩所需要时间 \]

我们分两种情况考虑:

  • \(1\) 号充电桩出发所需要的时间为

\[dis(1,j)+j点前往最近充电桩的时间 \]

  • 从除 \(1\) 号以外充电桩 \(i\) 出发所需要的时间为

\[dis(i,j)+j点前往最近充电桩的时间-i点前往最近充电桩的时间 \]

对于每次行走计算过程中的峰值电量判断是否合法,找到所有路径后跑 \(Dijskra\) 即可。

总结

本题考察了简单图论问题的转化,同时需要掌握 \(NOIP\) 的热点算法单源最短路。

期望均分:\(60-100\)

C - 题解

考察内容

  • dp
  • 复杂度优化
  • 猜结论
  • 单调栈

Subtask1(20pts)

对于每一块积木,我们记录它左侧积木的高度并枚举它的高度,使用 \(dp[n][h]\) 记录最优解并转移。

时间复杂度 \(O(n^2h)\).

Subtask2(40-60pts)

\(dp\) 中包含高度显然会使复杂度无法接受。

我们考虑最后操作的每个发生改动的连续段 \([L, R]\)。这时\(L-1, R+1\) 两块积木没有发生过改动;可以得到一个重要结论:

\([L, R]\) 中所有积木一定为相同高度

一个简单的证明:如果他们未被调整到同一高度,那么在操作其中最高的积木时少加一块,一定会使答案更优。

考虑我们目前走到第 \(i\) 块积木,枚举 \(j\) 使得 \([j+1, i-1]\) 是一个发生改动的连续段,并且这一段的所有积木会被加高到 \(H\) 的花费。

\[dp[i]=min(dp[j]+\sum^{i-1}_{k=j+1}(H-h[k])^2+(h[i]+h[j]-2*H)*c) \]

后面关于 \(H\) 的式子是一个关于 \(H\) 的二次函数,可以很容易地 \(O(1)\) 求出最小值,之后暴力转移即可。

时间复杂度 \(O(n^2)\),依据实现可能获得 40~60pts 不等。

Sol(100pts)

考虑如何优化之前的 \(dp\)

于是考虑怎么优化枚举,不难发现只有当 \(max_{k=j+1}^{i-1} h[k] \leq min(h[i],h[j])\) 时,转移才有可能更优。

由于比每一个点高的点只会转移一次,我们可以直接使用单调栈完成该操作。

只需维护一个单调递减的栈,每一次在栈中转移更矮的点,同时将元素一个一个弹出,直到转移到比它高的为止。

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

总结

本题考察了 \(NOIP\) 中常出现的一类 \(dp\) 状态设计:通过分析题目结论来优化掉式子中较坏的一维;同时最后一步使用了经典的单调栈优化。

期望均分:\(60-100\)

D - bank 题解

考察知识点

  • 线段树
  • 并查集
  • 矩阵基础
  • 图论

Subtask1(30pts)

暴力更新格点信息,询问直接DFS/BFS。

复杂度 \(O(NMT)\)

Subtask2(50pts)

使用线段树进行区间赋1操作。

询问等价于询问区间是否全为1,直接求和即可。

复杂度 \(O(TlogM)\)

Subtask3(70pts)

考虑每次修改只有一列,用线段树维护矩阵来维护连通性。

矩阵存储相邻两列的9种转移。

复杂度 \(27O(TlogM)\)

Sol(100pts)

考虑并查集维护答案。

第一种并查集维护图的连通性,第二种并查集每行维护一个,用来缩点,避免走重复的路。

考虑相邻两行并查集的合并,一定是某行的某个连通块走到尽头时和另一行合并。

总结

本题考察了线段树在具体问题上的应用;部分分设置上给了暴力一档以及简单区间赋值一档较高分数,希望能培养大家的写暴力能力。

期望均分:\(30-70?\)

posted @ 2025-10-17 21:23  杨佳明  阅读(6)  评论(0)    收藏  举报