2018.06.29 NOIP模拟 边的处理(分治+dp)

传送门
考试的时候读完题就感觉凉了,本蒟蒻和 y k yk yk神仙一起尝试暴力骗 20 20 20分, y k yk yk d p dp dp轻松过掉前 4 4 4个点,然而我连样例都没跑过,真是丢脸。

相信大家读完题后大家都能判断这是一道玄学 d p dp dp,但再一看数据范围,大家估计都想大骂出题人毒瘤了。言归正传,这题怎么做呢?准确的说,这题如何优化 d p dp dp呢?

好吧我们需要上一波分治,我们假设当前正在处理边的范围在 ( l , r ) (l,r) l,r之间的询问,区间的中点为 m i d mid mid那么对于每个询问,它的左右端点有三种情况

  1. 第一种情况:询问的右端点在 m i d mid mid的左边。
  2. 第二种情况:询问的区间恰好包含了 m i d mid mid
  3. 第三种情况:询问的左端点在 m i d mid mid的右边。

对于情况一和情况三,显然我们可以递归处理,对于情况二,就要用到我们的 d p dp dp了,由于题目上要求我们需要按序处理每条边。所以我们可以用 D P DP DP得到 l f [ i ] [ x ] [ y ] lf[i][x][y] lf[i][x][y]表示从 x x x出发,处理了从 i i i m i d mid mid的边之后到达 y y y的最小代价,以及 r f [ i ] [ x ] [ y ] rf[i][x][y] rf[i][x][y]表示从 x x x出发,处理了从 m i d + 1 mid+1 mid+1 i i i的边之后到达 y y y的最小代价,查询的时候只要枚举一下中间断点 k k k,然后执行状态转移方程 a n s [ q [ i ] . i d ] = m i n ( a n s [ q [ i ] . i d ] , l f [ q [ i ] . l ] [ k ] [ q [ i ] . u ] + r f [ q [ i ] . r ] [ k ] [ q [ i ] . v ] ) ans[q[i].id]=min(ans[q[i].id],lf[q[i].l][k][q[i].u]+rf[q[i].r][k][q[i].v]) ans[q[i].id]=min(ans[q[i].id],lf[q[i].l][k][q[i].u]+rf[q[i].r][k][q[i].v])就行了 。

怎么求 l f lf lf r f rf rf呢?我们可以对于每一个点先假设它不走新的边,那么 l f [ i ] [ u ] [ v ] = l f [ i + 1 ] [ u ] [ v ] + e [ i ] . r ; lf[i][u][v]=lf[i+1][u][v]+e[i].r; lf[i][u][v]=lf[i+1][u][v]+e[i].r;并且 r f [ i ] [ u ] [ v ] = r f [ i − 1 ] [ u ] [ v ] + e [ i ] . r ; rf[i][u][v]=rf[i-1][u][v]+e[i].r; rf[i][u][v]=rf[i1][u][v]+e[i].r;,如果这个点可以走新的边,那么我们用这条边连接的另外一个点的 l f lf lf r f rf rf的值来更新当前点的,也就是 l f [ i ] [ u ] [ e [ i ] . y ] = m i n ( l f [ i ] [ u ] [ e [ i ] . y ] , l f [ i + 1 ] [ u ] [ e [ i ] . x ] + e [ i ] . c ) ; l f [ i ] [ u ] [ e [ i ] . x ] = m i n ( l f [ i ] [ u ] [ e [ i ] . x ] , l f [ i + 1 ] [ u ] [ e [ i ] . y ] + e [ i ] . c ) ; lf[i][u][e[i].y]=min(lf[i][u][e[i].y],lf[i+1][u][e[i].x]+e[i].c);lf[i][u][e[i].x]=min(lf[i][u][e[i].x],lf[i+1][u][e[i].y]+e[i].c); lf[i][u][e[i].y]=min(lf[i][u][e[i].y],lf[i+1][u][e[i].x]+e[i].c);lf[i][u][e[i].x]=min(lf[i][u][e[i].x],lf[i+1][u][e[i].y]+e[i].c); r f [ i ] [ u ] [ e [ i ] . y ] = m i n ( r f [ i ] [ u ] [ e [ i ] . y ] , r f [ i − 1 ] [ u ] [ e [ i ] . x ] + e [ i ] . c ) ; r f [ i ] [ u ] [ e [ i ] . x ] = m i n ( r f [ i ] [ u ] [ e [ i ] . x ] , r f [ i − 1 ] [ u ] [ e [ i ] . y ] + e [ i ] . c ) ; rf[i][u][e[i].y]=min(rf[i][u][e[i].y],rf[i-1][u][e[i].x]+e[i].c);rf[i][u][e[i].x]=min(rf[i][u][e[i].x],rf[i-1][u][e[i].y]+e[i].c); rf[i][u][e[i].y]=min(rf[i][u][e[i].y],rf[i1][u][e[i].x]+e[i].c);rf[i][u][e[i].x]=min(rf[i][u][e[i].x],rf[i1][u][e[i].y]+e[i].c);

另一方面,为了给下一层的递归做准备,我们可以类比整体二分的思想,利用辅助数组重新排列修改过的 q q q的顺序,实现细节详见代码。
代码

你可能感兴趣的:(#,分治)