【训练日记】20170328
今天的题目似乎很水……?好多人都提前AK离场了,于是提前一小时收题。
但是我还是各种不会。
思维江化???
话说,听到一句很有趣的话:
山不在高,有林则徐;水不在深,有江……
T1
题意:给定一棵有N(N≤105)个节点的有根树,编号互不重复。询问有多少棵子树内节点编号构成一个连续区间。
题解:水题,对于每个节点i,记录以该节点为根的子树中最大和最小节点的编号Max(i)、Min(i)以及子树的节点个数Weight(i),若该子树内节点编号构成连续区间,则Max(i)−Min(i)=Weight(i)−1。
开场秒掉一题,开开心心对拍完,然后就开始了噩梦……
T2
题意:对于一个1∼n(n≤1001)的排列,定义一种表示方式。若排列中相邻两个元素后面一个大于前面,用I表示;若前面大于后面,用D表示。如排列3,1,2,7,4,6,5可以表示为DIIDID。现给出一个长度为n−1的排列表示,问有多少种排列满足这种表示。排列由I、D、?组成,?表示该位置既可以是I,也可以是D。
题解:考虑动态规划。用f[i][j]表示排列的第i位在i∼n−1位中是第j小的数的情况的排列数。若字符串的第i−1位为I,则f[i][j]=Σjk=1f[i−1][k]。D和?同理。观察发现该转移方程可以用前缀和优化,实现O(1)转移。
似乎很水的一道题,但是考场上完全没有思路。DP经验还是不足啊。
T3
题意:给定两个字符串X、Y(1≤|X|,|Y|≤1000)。令L为X和Y的最长公共子序列长度,询问X的所有长为L的子序列中,有多少个也是Y的子序列。
题解:再次考虑动态规划。首先O(n2)预处理出dp数组,其中dp[i][j]表示X串长为i的前缀与Y串长为j的前缀的最长公共子序列长度。转移方程:
dp[i][j]={max(dp[i−1][j−1],dp[i−1][j],dp[i][j−1])max(dp[i−1][j],dp[i][j−1])X[i] = Y[j]X[i]≠Y[j]
(似乎这样写很丑……)
接着用dp数组计算f数组。f[i][j]表示X串长为i的前缀中,长度恰好为dp[i][j]的子序列,且同时也是Y串长为j的前缀的子序列的个数。记p[i]为Y串中第i个字符,在它之前与它相同的字符的最大下标。
f[i][j]+={f[i−1][p[j]−1]f[i−1][j−1]X[i] = Y[j],dp[i][j] = dp[i - 1][p[j] - 1] + 1dp[i][j] = dp[i - 1][j - 1]
f[|X|][|Y|]即为答案。
思维难度略高于上题……考场上完全想歪了Orz。
日常训练无限垫底,要振作起来啊。
稻花香里说丰年,听取WA声一片。老老实实写小暴力、对拍!