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还没过,万一我代码炸了 回来再改。。。
原文地址:https://www.cnblogs.com/zhugezy/p/12262356.html