CF1917F
大常熟另类做法。不用排序。
要求直径长度,则想到把直径这一条链拎出来处理。然后考虑其他边会接在哪里,发现树最优情况下一定是一个毛毛虫的形式。更进一步,所有边都挂在接近直径中点的点上。
然后再考虑这些不在直径中的,长度为
于是考虑一个 dp:设
在 bool 值下运算。
如果有
发现有一点小问题:有可能一个
然后发现上面两个东西都可以用 bitset 维护,然后就可以
但是常数大,如果你在代码里多用左移/右移好像会 TLE,尽量少用,卡卡就过了。cf 机子真是令人流汗。
code:
点击查看代码
int n,m;
bitset<N> dp[2][N],f[2][N];
void Yorushika(){
scanf("%d%d",&n,&m);
rep(i,0,m)dp[0][i].reset();
rep(i,0,m)f[0][i].reset();
dp[0][0].set(0),f[0][0].set(0);
bitset<N> ALL;ALL.set();
rep(i,1,n){
int x,p=i&1;scanf("%d",&x);
rep(j,0,m)dp[p][j].reset();
rep(j,0,m)f[p][j].reset();
bitset<N> S;
rep(j,0,x)S.set(j);
rep(j,0,m){
dp[p][j][x]=(dp[p^1][j]&S).any();
dp[p][j]|=dp[p^1][j]&(ALL^S);
}
rep(j,x,m)dp[p][j]|=dp[p^1][j-x];
rep(j,x,m){
f[p][j]|=f[p^1][j-x];
f[p][j]|=f[p^1][j-x]<<x;
}
rep(j,0,m)f[p][j]|=f[p^1][j];
}
bool ans=0;
rep(i,0,m)rep(j,0,m)ans|=f[n&1][m][i]&&dp[n&1][i][j]&&j<=min(i,m-i);
puts(ans?"Yes":"No");
}
signed main(){
int t=1;
scanf("%d",&t);
while(t--)
Yorushika();
}