F-xay loves trees
考虑在树1中满足条件的一些点,首先不难想到一定是一条链,其次如果点 u u u被选择那么在树2以 u u u为根的子树的点就禁止被选,于是只需区间+,然后查询区间最值是否存在>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;
}