2019南昌网络赛Hello 2019(cf 750E)线段树_算法日常[24/100]
题目小趣事
我在比赛一开场就开始看这题,然后没想出怎么写,12:07我校一个大佬lxc说他拿下了这题的一血,这是一个原题,cf 750E(我只能说:大佬都是移动题库!)然后做完另一个签到题之后,成为第一名,带榜了
赛后发现1
Hello 2019 的提交情况如下:
通过率:5.66% 正确提交 / 总提交:217 / 3837
达成学校带崩他校节奏的成就
赛后发现2
这题**tourist(codeforces霸榜第一,ACM world final 4小时ak第一人,被评为全球最厉害的十个程序员之一(和c语言之父这些人在一个榜单!))**当年比赛的时候也没有做出来!然后大家说自己竟然尝试了一下当年T神都没有做出来的题目
题目链接
题意
给你一个串,然后多次询问左右区间,看删除多少个字符能使得这个区间内有9102,而没有8102的subsequence(codeforces中是有2017而没有2016)
题解
- 肉眼做法,表层理解,很容易看出只要删除8
- 因为8放在第一个不好处理,所以改成翻转string,并且翻转l,r,从而变成判断有2019没有2018,
- 因为每次询问一个区间,所以需要把dp状态扔到某个数据结构上,所以我们考虑线段树
- 线段树更新的时候是拿两段的信息合并,所以不能像做1~n的dp那样记录状态
考虑2017之间的间隔:
| 2 | 0 | 1 | 9 |
0 1 2 3 4
线段树的每个节点存一个矩阵A.$mat_{ij}$表示使原串的子序列包含2019中第i个间隔到第j个间隔组成的子串,但不严格包含它的子序列最少需要删除的数字、
转移是显然的,和区间dp一样。枚举区间,枚举中间点,然后转移就好了。
考虑初值问题,显然的是非2、0、1、9、8的数字对答案不影响,所以令$a_{ii}$=0,$a_{ij}$=N(取不到就行) (i!=j)
考虑当前数字是2的时候,如果我希望只包含子串[0,0](这里表示两个间隔间的子串),那么就必须删掉这个2,故$a_{00}$=1(可以理解为不想要成为2019是不思进取的行为,所以付出代价–>这样可以在后面处理的时候淘汰掉这些大的状态值),如果希望包含子串[0,1],那么什么都不用做,所以$a_{01}$=0。对于0、1、7同理。
考虑当前数字是8的时候,那么遇到子串[i,3]希望转移回自己(不想接受8来到达4状态),那么需要付出1的代价,因为否则会包含子序列”2018”,同样如果遇到子串[i,4]希望转移回自己(不想接受8来到达4状态),那么也需要付出1的代价(区间如果询问到这里就是真正要删除的数字了,因为4达到状态终点了)。
AC代码
1 |
|
参考链接
每天一句叨叨
这个世界,想不想要永远不是最重要的,重要的,是要不要得起。
就像每个人都想成功,但是不是每个人都承担得起成功的代价