CF2041
一场 ICPC,写几个题的题解。
A
用 \(15\) 减去四个输入即可。
D
图论题,考完发现都写的是 dijkstra,但是我写的是 BFS。
模板是基础,然后对于每个状态记录现在的方向和朝这个方向连续走了多少次,显然,当次数等于 \(4\) 时,你需要换方向,如果要沿同一防线继续走,就需要后退一步再前进两步。
这时就有 hack 来卡我了,如果按照这种方式连续朝同一方向前进,那么这样后退再前进的花费会是 \(2\),也就是消耗了一次向前走的机会。但是,如果现在的左右(或上下)有空格子,你可以向别的方向换一下,再朝原方向前进,这样花费是 \(1\)。举个例子:
S.........T
...........
这样的路,你可以直接直线行走,也可以向前走两格再向下移动,再回来,是更优的。
有个细节,就是优先队列中有位置相同,答案相同,但是方向来源不同的点,为了保证正确性,你需要把符合这些条件的所有点全部跑出来,而不是只取第一个,有这样一个 hack 数据,找到了我在赛时错误(来自 Baiyj):
5 18
S................T
.################.
.################.
..##....##....##..
..................
E
构造题。首先,一定有一个长度为 \(3\) 的序列满足条件,因为要满足平均数是 \(a\),中位数是 \(b\),设三个数是 \(x,y,z\) 其中 \(x<y<z\),那么有
选定一个 \(x\) 就可以了,注意有可能 \(x,z\) 都小于 \(y\),判断一下就会。
M
贪心题。
题目给这定两个函数:
-
前缀排序函数:选择 \(\forall i\in [1,n]\),把区间 \([1,i]\) 排序,花费代价是 \(i^2\);
-
后缀排序函数:选择 \(\forall i \in [1,n]\),把区间 \([n-i+1,n]\) 排序,花费代价是 \(i^2\)。
给出一个序列,问你把它排成升序序列的最小花费。
观察可以发现,一定是一次前缀一次后缀,并且排序的次数一定不大于 \(2\)。
证明:
考虑先前已经经过了一次前缀排序,再进行一次前缀排序一定会涉及前面已经有序的区间,会使得答案不优。因为我们答案更优一定要让越少的地方被多次排序。
那么策略就很明显了,首先,如果选定一个位置 \(i\) 做前缀排序,一定可以找到另一个位置 \(j\) 做后缀排序,使得序列有序。易得极端情况下 \(j\) 取 \(1\) 一定可以满足。先后缀排序再前缀排序同理。
那么,我们如何找到这个位置呢?
以先前缀再后缀为例,假设排完前缀,前 \(k\) 小的数已经到前 \(k\) 个位置,那么第二次排序一定是从 \(k+1\) 开始排的。也就是说,若当前排好的序列中有 \(k\) 个前 \(k\) 小(或大)的数,那么第二次排序的位置就是 \(k+1\)。
预处理很简单,用优先队列即可。
有一个小细节,就的形如 321456897
的序列,先给 \(3\) 前缀排序,你会发现第二次排序的位置是 \(7\),也就是有可能有更多的有序位置在后面(或前面)出现,特判一下就好。