zhugezy

Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F

C

对每一步结束之后往map里存个位置,看停留在相同位置的最少差多少步就行了。

D

\(h\%(a+b)\leq (x+1)a\)\(x_{min}=\lceil\frac{h\%(a+b)}{a}\rceil-1\).然后贪心即可。

E1

注意到要把原字符串排序,每一对逆序对都要进行一次交换,即每一对逆序对的颜色都必须不同。因此所需的颜色数即为最长的逆序链长。

对E1,可以考虑建图,每个位置看成一个点,把每一对逆序对建边,很显然这就是判断是不是一张二分图。

E2

对E2,依次考虑字母a,b,c,...,z,给每个字母填上它当前能填上的最小数字。例如对样例abacbecfd,考虑到字母c了,当前字符串和涂色为

aba(c)b?(c)??
121(?)1?(?)??

对新加入的每个字母c,看在它后面的小于它的字母(a/b)的那些位置,填上大于那些数字的最小数字。

第一个c后面有一个b,为一对逆序对,所以c应填大于1的最小值2。后面的c应填1。

正确性的证明:

首先,对每个新加入的字母x,如果有小于x的字母y在x后面出现,那么x的数字一定大于y的数字。这保证了逆序对<x,y>一定能够进行交换。因此所有逆序对都能得到交换。

至于怎么证它的最优性,我还不会= =,但是大概可以意会出来XD

然后上面这个算法抽象出来就是两种操作:

一开始有数组\(a\),初始值均为0。

1.给出\(i\),查询区间\([i,n]\)的最大值

2.给出\(i\)\(x\),更新\(a_i=x\)

用什么去搞就不用我多说了8

F

先把每个约束条件\((a,b,v)\)拆成\((S,v)\),其中\(S\)是从\(a\)\(b\)的边的集合。我写了个巨丑无比的LCA,可能有别的写法。

把约束条件按边权大小排序,从大到小处理。假定当前边权是v,其对应若干条路径,这些路径组成的边集为\(\{l_1,l_2,...,l_k\}\),则需把这些边中还没有赋权的边全部赋权v,因为:

1.如果把已经赋权的边更改为更小的这个v,则不满足前面处理过的条件;

2.如果把还没赋权的边不赋权v而是留着,则它可能会被之后的约束条件赋成一个更小的权,不满足这个约束条件;

3.如果把还没赋权的边赋成一个大于v的值,可行,但是代码实现不太简单。

这样能保证我造出来的树对每个约束条件\((S,v)\),满足\(S\)的所有边权都\(\geq v\)。接下来只需直接check每个条件就能知道是否合法了。为什么?

这个方法每条边最多只会被赋值1次,在约束条件中的边也一定会被赋值。直接check等价于对每一层边权v,去check是否每一个约束条件都被满足,这又等价于check每一层边权v中,对每个约束条件,是否都有至少一条边被赋值为v。

举个例子:

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

先处理\(val=5,S=\{(1,2),(3,4)\}\),把这两条边都赋值5。

再处理\(val=3,S=\{(2,3),(3,4)\}\),把\((2,3)\)赋值3。结束。

后记

这个div3打得我属实没劲,主要还是我容易把代码敲的太复杂。。。尤其是F,我敲了130多行,不太能理解60行以内的代码是怎么敲出来的,可能做法也不太一样吧。

system test还没过,万一我代码炸了 回来再改。。。

posted on 2020-02-05 02:57  zhugezy  阅读(340)  评论(0编辑  收藏  举报

导航