[toc]
A Blank
计数dp,长为n的数列,每个位置上四种数字选择,题目会给出m个限制条件,每个条件要求在[l,r]范围内有且仅有几种数字。要求给出所有合法方案数。
我们可以用dp来对每种数字上次出现的位置做情况讨论,例如用dp[x][y][z][w][len]来表示0123上次出现位置分别在xyzw、当前读取到第len个字符时共有多少种方案数。然后对于r=len的限制条件,我们查看在l之后出现过的数字种数是否符合要求,即xyzw中大于等于l的有几个。
优化:由于四个位置中必定有一个等于len,所以我们可以减少一个维度,令dp[x][y][z]表示较远出现的三个数字的位置,并且设定顺序,要求x>=y>=z。当且仅当=0时等号可能成立(均未出现过),不会出现两种数字占用同一个格子。
1 |
|
B Operation
给出一列数。两种操作,对于区间[l,r]挑一些数得到最大的异或和并输出,以及在数列后面附加上一个新数字。
前缀线性基。
我们用p[n][i]中的p[n]表示到1~n个数形成的线性基,同时用pos[n][i]记录每个线性基需要用到的最左边的数的位置。这样在给定区间[l,r]时,我们对于线性基p[r],判断其中的基的pos是否大于等于l,如果是则这个基是合法的。因此我们在建立线性基时如果遇到相同的有效位,优先采用靠后的那,同时在执行接下来的削减最高位的操作时,要注意它需要用到左边那个数做减数,所以此时pos指向左边那个数的位置。
1 |
|
C Milk
这题是真的难……多部分dp的组合拼接,看别人的博客想了好久才理解。并且最后依然没有A掉,不知道卡在什么地方了。代码是这样的。
1 |
|
我觉得单独一个部分的dp就差不多够我做了。
F Typewriter
给定一个字符串,用两种方法逐步构造它,可以在字符串后面以p代价附加任一字符,也可以复制已生成字符串的任一段子串到最后,代价q。求构造的最小代价。
后缀自动机+dp
dp[i]表示构造到第i位时的最小代价,显然满足dp[i]=min(dp[i-1]+p,dp[j]+q),其中j+1到i的字符串可以从1到j的子串复制过来,同时我们可证明dp数组是一个不降序列,因此这里的j我们取最小的一个。
在对每一个dp[i]更新时,我们需维护这个j,实际上是在维护后缀自动机中的一个状态,首先这个状态代表的后缀要以s[i]结尾才是合法的,进而满足这个后缀集合中最长的一个要大于等于i-j,在此基础上它可以尽可能地向父亲跳,因为从父亲的next可能性更多。当某个状态没有通向s[i]的next时,我们需要再加入一个点,即执行extend(s[++j])。
1 |
|
I String
给一个字符串,要求寻找长度为k、字典序最小的子序列,其中每个字母都要满足一个限定条件,即出现次数在[L,R]之间。
从0到k-1逐位贪心构造结果串,即对每一位从a到z尝试是否合法,合法则选用再看下一位。合法共需满足四个条件(看代码)。
用到了序列自动机,就是一个记录了每个位置后某个字母第一次出现在哪里的数组。
1 |
|