$\text{Description}$
有n个数列,每个数列长度可能不一样,同时有一个c,你有一种操作,让这n个数列中所有小于c的数都加1,所有等于c的数变成0.问你最少可以操作几次可以让这n个数列满足字典序.
$\text{Solution}$
我们可以发现,对于任意两个相邻的数列,操作数k有一个符合的区间,且k一定小于c,因为进行c次操作之后的数列与原数列相同,相当于有一个循环的过程。只要操作数k在这个区间里面,上面的数列字典序总小于下面的数列。说得通俗一点,有n-1个区间(有特殊情况,看代码),要求这n-1个区间的交。
怎么做这个问题呢,我们可以采取差分+前缀和的方式进行处理,具体方法就是区间两端位置放个++和—,统计时从前到后加起来就可以了。
下面来讨论一下每种情况:
首先假设有两个word,分别叫做a和b,并且我们定义两个word的失配位置为两个word从前往后逐位比较,所找到的第一个有不相同字符的位置。
具体情况有一下四种:
1.失配位置在a,b中(表示没有一个word是另一个word的前缀),且失配位置上的数a比b小。
举个栗子 a=13
b=15
c=7
明显地,失配位置在第二位,失配位置上的数满足a比b小。画个表格模拟一下:
操作次数 | a | b |
---|---|---|
0 | 13 | 15 |
1 | 24 | 26 |
2 | 35 | 37 |
3 | 46 | 40 |
4 | 57 | 51 |
5 | 60 | 62 |
6 | 71 | 73 |
可以看出,失配位置前的数字对结果不产生影响(因为始终相同,无法比较字典序),由表格易知当操作数在$[0, 2] \cup [5, 6]$的情况下是可行的。这个情况比较复杂,因为举其他例子时有可能第二个区间退化成一个数甚至消失,这会不会对我们的程序产生什么影响呢(比如说要特判之类的)?答案是不会。因为假设第二个区间的形式是$[p, q]$,第二个区间消失时一定满足$p = q + 1$(这个很重要,要自己多举几个例子理解一下,我这里就不证明了),而我们的程序会在$p$的位置+1,在$q + 1$的位置-1,两个加一减一相互抵消了,因此对我们的程序不产生影响。
2.失配位置在a,b中(表示没有一个word是另一个word的前缀),且失配位置上的数a比b大。
仍然举个栗子 a=14
b=12
c=7
,这个相对较易,我就不画表格模拟了,操作数的区间为$[4, 5]$
3.失配位置在a的末尾的后一个位置(a是b的前缀),这个很简单不管你怎么操作a始终比b小,操作区间$[0, c - 1]$
4.失配位置在b的末尾的后一个位置(b是a的前缀),这个也很简单,直接就是无解,不需要进行任何操作,直接输出无解可以,continue也可以(缺少一个区间就永远无法让k满足n-1个区间)。
四种情况讨论完了,具体详情看代码吧。
$\text{Code}$
1 | #include<cstdio> |