F-xay loves trees
考虑在树1中满足条件的一些点,首先不难想到一定是一条链,其次如果点uuu被选择那么在树2以uuu为根的子树的点就禁止被选,于是只需区间+,然后查询区间最值是否存在>1也就是树2中覆盖次数超过2的节点即可。
首先不难想到可以二分链的长度,在树1中进行dfs用双端队列维护维护长度是len的链 2log跑不过。
假如我们dfs到某个点我们假如我们发现长度为len是可以那么我们就可以保存这个长度去维护滑动窗口类似!因为答案肯定不会比len还短,维护短的没意义,那么这个长度就是单调递增的,那么这样就没二分了!
黑夜和白天大佬题解
Code1 二分
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int rd()
{int res=0;char ch=getchar();while(!isdigit(ch)) {ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=300010;
int h1[N],e[N<<2],ne[N<<2],idx;
int h2[N];
void add(int h[],int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int sz[N],dfn[N];
int n,timestamp;
void dfs1(int u,int fa)
{sz[u]=1;dfn[u]=++timestamp;for(int i=h1[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs1(v,u);sz[u]+=sz[v];}
}
int len;
bool ok;
int q[N],tt;
int val[N<<2],tag[N<<2];
void pushdown(int u)
{if(tag[u]==0) return;tag[u<<1]+=tag[u];tag[u<<1|1]+=tag[u];val[u<<1]+=tag[u];val[u<<1|1]+=tag[u];tag[u]=0;
}
int dep[N],f2[N];
void dfs3(int u)
{for(int i=h2[u];i!=-1;i=ne[i]){int v=e[i];if(v==f2[u]) continue;dep[v]=dep[u]+1;f2[v]=u;dfs3(v);}
}
void modify(int u,int l,int r,int L,int R,int v)
{if(L<=l&&r<=R) {val[u]+=v;tag[u]+=v;return;}pushdown(u);int mid=l+r>>1;if(L<=mid) modify(u<<1,l,mid,L,R,v);if(R>mid) modify(u<<1|1,mid+1,r,L,R,v);val[u]=max(val[u<<1],val[u<<1|1]);
}
void dfs2(int u)
{if(ok) return;int cur=dep[u];if(cur>=len) {int v=q[tt-len+1];modify(1,1,n,dfn[v],dfn[v]+sz[v]-1,-1);}q[++tt]=u;modify(1,1,n,dfn[u],dfn[u]+sz[u]-1,1);if(cur+1>=len){ll tot=val[1];if(tot<=1) ok=1;}for(int i=h2[u];i!=-1;i=ne[i]){int v=e[i];if(v==f2[u]) continue;dfs2(v);}--tt;modify(1,1,n,dfn[u],dfn[u]+sz[u]-1,-1);if(cur>=len) {int v=q[tt-len+1];modify(1,1,n,dfn[v],dfn[v]+sz[v]-1,1);}
}
bool check(int x)
{len=x;ok=0;tt=0;dfs2(1);return ok;
}
void init()
{for(int i=1;i<=n;i++) h1[i]=h2[i]=-1;idx=timestamp=0;tt=0;for(int i=1;i<=n;i++) dfn[i]=sz[i]=0;for(int i=1;i<=n;i++) dep[i]=f2[i]=0;
}
int main()
{int Tc=rd();while(Tc--){n=rd();init();for(int i=1;i<n;i++){int u=rd(),v=rd();add(h2,u,v);add(h2,v,u);}for(int i=1;i<n;i++){int u=rd(),v=rd();add(h1,u,v);add(h1,v,u);}dfs1(1,0);dfs3(1);int l=1,r=1+*max_element(dep+1,dep+1+n);while(l<r){int mid=l+r+1>>1;if(check(mid)) l=mid;else r=mid-1;}printf("%d\n",l);}return 0;
}
Code2 优化
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int rd()
{int res=0;char ch=getchar();while(!isdigit(ch)) {ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=300010;
int h1[N],e[N<<2],ne[N<<2],idx;
int h2[N];
void add(int h[],int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int sz[N],dfn[N];
int n,timestamp;
void dfs2(int u,int fa)
{sz[u]=1;dfn[u]=++timestamp;for(int i=h2[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs2(v,u);sz[u]+=sz[v];}
}
int val[N<<2],tag[N<<2];
void pushdown(int u)
{if(tag[u]==0) return;tag[u<<1]+=tag[u];tag[u<<1|1]+=tag[u];val[u<<1]+=tag[u];val[u<<1|1]+=tag[u];tag[u]=0;
}
void modify(int u,int l,int r,int L,int R,int v)
{if(L<=l&&r<=R) {val[u]+=v;tag[u]+=v;return;}pushdown(u);int mid=l+r>>1;if(L<=mid) modify(u<<1,l,mid,L,R,v);if(R>mid) modify(u<<1|1,mid+1,r,L,R,v);val[u]=max(val[u<<1],val[u<<1|1]);
}
void update(int u,int v){modify(1,1,n,dfn[u],dfn[u]+sz[u]-1,v);}
int ans;
int q[N],tt,hh;
void dfs1(int u,int fa)
{int cur=-1;q[++tt]=u;update(u,1);if(val[1]==1) ans=max(ans,tt-hh+1);else if(tt-hh+1>ans){cur=q[hh++];update(cur,-1);}for(int i=h1[u];i!=-1;i=ne[i]) if(e[i]!=fa) dfs1(e[i],u);if(cur!=-1) {update(cur,1);q[--hh]=cur;}update(u,-1);--tt;
}
void init()
{for(int i=1;i<=n;i++) h1[i]=h2[i]=-1;for(int i=1;i<=n;i++) dfn[i]=sz[i]=0;for(int i=1;i<=4*n;i++) tag[i]=val[i]=0;idx=timestamp=hh=ans=0;tt=-1;
}
int main()
{int Tc=rd();while(Tc--){n=rd();init();for(int i=1;i<n;i++){int u=rd(),v=rd();add(h1,u,v);add(h1,v,u);}for(int i=1;i<n;i++){int u=rd(),v=rd();add(h2,u,v);add(h2,v,u);}dfs2(1,0);dfs1(1,0);printf("%d\n",ans);}return 0;
}