T1:这题其实很简单。
对于那些传送门操作,我们设a、b、c、d分别表示一个位置到上下左右的最近一个#的距离,那么我们会发现其实这个点到这4个点的距离可以用min(a,b,c,d)来替换。即a、b、c、d可以用min(a,b,c,d)来替换。
这样我们就可以预处理出每一个点的a、b、c、d,然后直接SPFA即可。
T2:首先按key从小到大排序,然后树的先序遍历就出来了。
这题的一中解决方案就是每次从当前区间中选取一个点作为当前区间的根。通过这个思想我们可以设出dp方程:设f[i][j][k]表示i~j这段区间选k为根的最大和。这是一个区间dp,可以枚举两边区间的根,转移方程不难推。
但是我们发现这个dp的时间复杂度是O(n^5)的,需要优化。接着我们发现其实i~j这一个区间从k分开之后,i~k-1连向的根就是(k-1)+1,k+1~j连向的根就是(k+1)-1。这就说明i~j这个区间的上一级根要么是i-1,要么是j+1。这样我们就可以简化状态:设f[i][j][0/1]表示i~j这个区间的上一级根为i-1(0)或j+1(1)时的最大和。
那么转移方程就从f[i][j][k]=max(f[i][k-1][g1]+f[k+1][j][g2]+……)变成f[i][j][0/1]=max(f[i][k-1][1]+f[k+1][j][0]+……)。
这样问题就解决了。
总结:比赛时空超,下面说一下如何精确计算KB数的方法。
首先,1KB=1024B,1B=8字节。而一个int占32字节(就是4B),一个long long为int的两倍(即64字节、8B)。
这一题如果开f[300][300][300]的话就是27000000*8/1024=210937.5KB,显然超限。
T3:首先我们发现对于一个i和a[i],如果要它对答案有贡献的话,那么必须要i-l=r-a[i](l、r为翻转的区间)。
变一下可以得i+a[i]=l+r,其实这个式子的本质就是他们的中点相同。
那么我们可以把所有i和a[i]根据i+a[i]排序,对于相同和的,我们按它的左端点从大到小排。
接下来我们就枚举翻转区间,ans=max(之前的和当前翻转区间的i+a[i]相同的区间的个数+没被翻转部分的答案)。