2019.10.07题解
有点遗憾,T2题理解错了爆了45分,T3打的正解忘记是long long内存炸掉了。
T1
首先可以用1.3s左右筛出1e7个质数,之后我们发现每次区间移动只会改变2个值,所以可以用两个指针记录中位数,每次的移动可以看成常数级的。
ps:bitset真玄学,cbx因为用bitset CE了(不加万能库就没事)。而且bitset很吃O2,不开跑9s,开了跑进2s
T2
我们发现每次加入一个点之后要么拿掉它,要么以后拿这次拿集合的最大值,无论怎样集合的最大值不会变大,所以考虑用一个单调指针维护最大值的位置,复杂度$ O(nk) $
T3
正解挂分系列,给每个点开8个200大小的tmp数组,内存用int算的,打完调完才发现是long long,其实还是考试心态不行,先把子树全dfs一遍再去更新答案的思路应该是挺好想到的,但是当时就是太慌了。
我的思路:
设dp[0/1][i][j]为到i点从上到下/从下到上用了j次面包的最大收益。
首先考虑子树的合并:(懒得写了,直接上代码吧)
for(int j=0;j<=m;j++) { f[0][j]=max(f[0][j],dp[0][y][j]),g[0][j]=max(g[0][max(0ll,j-1)],f[0][j]); f[1][j]=max(f[1][j],dp[1][y][j]),g[1][j]=max(g[1][max(0ll,j-1)],f[1][j]); d[0][j]=max(d[0][j],dp[0][y][j]-p[y]),h[0][j]=max(h[0][max(0ll,j-1)],d[0][j]); d[1][j]=max(d[1][j],dp[1][y][j]-p[y]),h[1][j]=max(h[1][max(0ll,j-1)],d[1][j]); }
再以x点为lca更新ans
for(int j=0;j<=m;j++) { ans=max(ans,g[0][m-j]+dp[1][y][j]); ans=max(ans,g[1][m-j]+dp[0][y][j]); if(j!=m) ans=max(ans,g[0][m-j-1]+dp[1][y][j]+s[x]-p[y]); if(j!=m) ans=max(ans,h[1][m-j-1]+dp[0][y][j]+s[x]); }
最后把子树传给x
for(int j=0;j<=m;j++) { dp[0][x][j]=max(0ll,f[0][j]); if(j) dp[0][x][j]=max(dp[0][x][j],f[0][j-1]+s[x]-p[fa]); dp[1][x][j]=max(0ll,f[1][j]); if(j) dp[1][x][j]=max(dp[1][x][j],d[1][j-1]+s[x]); ans=max(ans,dp[0][x][j]); ans=max(ans,dp[1][x][j]); }