Codeforces Round#826 (Div. 3) D E F
Codeforces Round #826 (Div. 3) D E F
D. Masha and a Beautiful Tree (递归)
题意:
对于每个样例,输入一个m,之后输入一个长度为m的排列(m好像保证一定是2^i
),输入的排列是一颗完全二叉树的叶子结点。你可以进行一种操作:操作每一个非叶子节点,交换他的两个左右儿子(左右子树也会跟着交换)。问你进行多少次操作可以使这个排列p满足$p_i = i$,输出最小的操作次数,无法操作输出-1。
分析:
二叉树是递归定义的。
可以考虑把这棵树看成一颗线段树,维护区间最大值(或者最小值),这样每个结点的值就都有了,我们假设叶子结点所在那层为第0层,其父亲结点在第1层,。。。,根节点在最高层,那么对于第i层的两个兄弟结点$p_1, p_2$,它们必须满足$|p_1 - p_2| = 2^i$,否则答案将是-1。对于操作,如果左儿子大于右儿子,则需要操作其父节点。二叉树是递归定义的,递归跑一遍即可(dfs)。
AC代码:
1 |
|
E. Sending a Sequence Over the Network(递推/简单dp)
题意:
对于一个长度为m的数组ar,可以将它分割成很多段($l_i,r_i$),任意一段没有交集,且所有段合起来是(1,n)之后在某一段的左边或者右边添加一个数字k,k为这一段的长度,由此获得数组br。
对于每一个样例,输入一个n,代表数组br的长度,之后输入数组br,问是否存在一个数组ar,经过操作后能够变成数组br。
分析:
定义一个bool类型数组vis,vis[i]
表示数组br中,位置i能否作为一段的终止,$O(n)$递推转移一下即可(对于每个点,枚举他作为区间最左或者最右的情况),注意不要re,答案就是vis[n]
。
AC代码:
1 |
|
F. Multi-Colored Segments (排序+维护前缀最大值和前缀次大值)
题意:
在一个数轴上有n个线段,对于每段线段,其左端点和右端点一定是整数,每个线段有一个颜色,两个线段的距离是从两个线段中分别选取两个点求两点间距离,这个距离的最小值为两个线段的距离(相交距离为0,不相交左面线段选右端点,右面线段选左端点)。对于每段线段,求离它最近的一个和它颜色不同的线段的距离。
分析:
对于线段$i$$(l_i,r_i,c_i)$,离它最近的且和它颜色不同的线段的距离可以分为两部分,位于$r_i$左侧的线段(如果线段$j$满足$l_j<=r_i$,则认为线段$j$位于其左侧)且于线段$i$颜色不同的线段距线段$i$的距离$s_1$,位于$l_i$右侧的且于线段$i$颜色不同的线段距线段$i$的距离为$s_2$,则$ans_i = min(s_1, s_2)$.
对于某个线段$i$,求其$s_1$,维护满足条件的线段$j$的$r_j$的最大值和次大值(最大值和次大值对应的线段颜色应当不同,即一种颜色只记一个最大值),若线段$i$与最大值对应线段颜色不同,则$s_1$由最大值决定(假设最大值是$mx$,则$s_1 = max(0,mx-r_i)$),否则由次大值决定。
由此,可通过排序+遍历取得,对于求$s_i$应将线段$i$所在数组按照$r_i$从小到大排序,线段$j$所在的数组按照$l_j$从小到大排序,之后遍历即可。而对于$s_2$,可以将线段的 $l=l\times(-1)$,$r=r\times(-1)$之后$swap(l,r)$,再按照上面求$s_1$的方法计算一遍即可得$s_2$ 。
AC代码:
1 |
|