【题解】CF1411D Grime Zoo

本题解约等于CF官方题解的翻译版+比较通俗易懂的解释+博主的胡诌八扯

 

题意:

一个01字符串,它当中每一个01子序列会获得x个愤怒评价(angry comment),每个10子序列会收到y个愤怒评价

子序列:可以不是连续的一段 比如011001有5个01子序列,4个10子序列(参考最长上升子序列)

这个字符串当中有一些尚未确定的数,用问号(?)表示

你的任务确定这些问号的值,使得愤怒评价尽可能少

输入这个字符串和x y

输出最少的愤怒评价数量

字符串长度n<=1e5

x,y<=1e6

 

题解

(下面的推导有点烦人,而且难以让人发现真正的思路时怎么来的,所以建议直接拉到最后结合更新的部分内容来看)

两个相邻的问号,设它们分别在l 和 r(l<r)

如果a[l]=0,a[r]=1

总愤怒评论数可以这样统计

l位置的0和(l,r)内部的1 : x * c1[l,r]

(l,r)内部的0和r位置的1 : x * c0[l,r]

l,r和[l,r]外部数字组成的二元组的贡献 : out

除去l r以外,其他数字的贡献(不受a[l]和a[r]的影响,优化时可以不考虑) : other

 

angry comment=x * c0[l,r]+x * c1[l,r]+out+other=x*(r-l-1)+out+other

 

同理,a[l]=1,ar[r]=0时

 

angry comment=y * c1[l,r]+y * c0[l,r]+out+other=y*(r-l-1)+out+other

注意到out和other在两种情况下是相等的,这里只需要优化第一项

即比较x*(r-l-1)和y*(r-l-1)那个更小

显然,直接比较x和y哪个小就行了

x<y时,对于两个相邻的'?',01优于10

x>y时,10优于01

看到这里难免有疑问,这样类似于爬山算法或者梯度下降法的优化,会不会陷于局部最优解?

会,但有办法解决

不妨假设x<y

对于任意可行解

比如0011011000

可以这样优化

0011011000

0011010100

0011010010

0011010001

0011001001

0011000101

0011000011

...

0000001111

你会发现优化的过程就是不断地把1后移(移动过程中,1的数量保持不变)

最优解一定前面全是0,后面全是1(如果不是的话,那么一定可以把0前面的一个,1后移一位,使答案优化)

但前缀0的长度是多少呢?很简单,枚举一下就好了,O(n)的

如果x>y,情况类似,反过来就好了

如果x=y 可以发现 如果0和1 的数量不变,那么答案是不变的,不妨按照x<y处理

回顾一下这一题的思路 先找到了一个优化的方法,确定了哪些一定不是最优解,以及 如果是最优解,那么它一定是什么样的,这样做可以缩小枚举范围,

一旦这个枚举范围可以接受,那么直接枚举就好了

说句题外话,这题的思路有点类似于求多元函数最小值的过程

对于一个定义在Rn上的可导函数f(x),如果▽f(x*)不是零向量,那么存在ε,使得f(x*-ε▽f(x*))<f(x*),所以x*一定不是最优解

如果argmin[x] f(x)存在,那么它一定满足▽f(x)=0

列个方程求出▽f(x)=0的所有解,如果只有有限数量的解,那么挨个枚举就完事了

 

UPD 2021-3-27

这里提供一个比较简单的角度:

当a里面1(或者0)的数量不变时,显然01序列和10序列的数量和是不变的

如果我们交换一对0和1(1在前面还是0在前面无所谓)

那么由于01和10的总和不变,那么可能会导致01和10的数量此消彼长

如果1在前,那么10减少,01增加,否则01减少,10增加

如果x<y,那么显然要让01尽可能地多,那么把尽可能把1放在后面就是最优解

posted @ 2020-12-22 19:59  LMXZ  阅读(178)  评论(0)    收藏  举报