Codeforces Round #708 (Div. 2)小结

前言:

D , E 2 D,E2 D,E2是两道比较有趣的dp题.记录一下.

D.题目大意:略

题目思路:新的图论模型(对最短路本质的理解)

显然有一个 n 3 n^3 n3的做法. d p ( i , j ) dp(i,j) dp(i,j) 代表现在站在 i i i,上一步来自 j j j的最优解.转移即可.但是并过不了这道题.要求 n 2 n^2 n2.简单分析可以发现我们的路径一定是从小走到大的.那么我们考虑这样一个图论模型:

给你一张无向带权图.每条边含有两个值 ( a i , b i ) , a i (a_i,b_i),a_i (ai,bi),ai 两两不同.让你走出一条 a i a_i ai严格递增的路径,使得 b i b_i bi累和最大.

自然定义 d p ( i , j ) dp(i,j) dp(i,j)只访问前 i i i大条边时,以 j j j结尾的最大值.

解释:因为我们每一步必须比上一步跨步要大.所以对于任意一个合法路径,一定是从小转移到大的.

如何转移,很类似bellman-ford算法的边松弛算法:也很显然.

令第 i i i大的边为 ( x , y , w ) (x,y,w) (x,y,w)

d p ( i , x ) = m a x { d p ( i − 1 , x ) , d p ( i − 1 , y ) + w } dp(i,x)=max\{dp(i-1,x),dp(i-1,y)+w\} dp(i,x)=max{ dp(i1,x),dp(i1,y)+w}

d p ( i , y ) = m a x { d p ( i − 1 , y ) , d p ( i − 1 , x ) + w } dp(i,y)=max\{dp(i-1,y),dp(i-1,x)+w\} dp(i,y)=max{ dp(i1,y),dp(i1,x)+w}

然后又因为每个长度都不同.那么可以直接优化掉一维.拿两个tmp装一装即可.然后对边排序松弛即可

然后又因为这道题卡内存.稍微找找规律 n 2 n^2 n2循环转移就ok.这题主要得分析清楚它模型本质,代码很好写.

拓展:

1.如果边权 a i a_i ai重复呢?

开滚动数组即可.

2.bellman-ford算法的dp本质定义: d p ( i , j ) dp(i,j) dp(i,j)代表从源点开始只经过少于等于 j j j条边到达 i i i点的最小花费.转移挺像背包的.

3.Dijstra算法的dp本质是 d p ( i , j ) dp(i,j) dp(i,j)代表已经确定了 i i i个点是最短路的从源点到 j j j的最短路.

总的来讲,这两个算法一个是对边松弛,一个是对点松弛.

E2.题目大意:略

思路:

首先有一点,如何快速判断两个数相乘是否某个数的平方?.

将数进行质因分解,对幂对2取模.得到 m a s k ( x ) mask(x) mask(x).

m a s k ( x ) = = m a s k ( y ) mask(x)==mask(y) mask(x)==mask(y)时, x ∗ y x*y xy为某个数的平方.

问题转化成:
给你一个序列,让你最多修改 k ( k ≤ 20 ) k(k \leq 20) k(k20)次.问你划分成最少段,使得每一段里面没有重复的数字.

预处理一个 l [ i ] [ j ] l[i][j] l[i][j]代表以 i i i为右端点,允许修改 j j j个值的能够衍生的最远的左端点 - 1.符合单调性,双指针处理即可.

然后对于每个点,作一个 O ( n k 2 ) O(nk^2) O(nk2)的背包dp即可.

猜你喜欢

转载自blog.csdn.net/qq_35577488/article/details/115018266