习题: Beard Graph(LCA&线段树)
题目
思路
考虑用一个魔性的方法来做这道题
如果直接用LCA来求,那么两个点之间的距离一定是正确的,
同时如果保证深度正确的前提下,也可以用\(dep_u+dep_v-2*dep_{lca}\)来求,
注意这里是需要保证深度正确,也就是指如果深度不正确,那么求出来也不正确
设深度深的节点为u
改变一条边,我们只需要将以u为根节点的子树的所有深度变得不正确或者正确即可
注意是子树内所有点的修改,即dfn的编号是连续的,用线段树来保证这种操作即可
当然巨佬们也可以用树链剖分来直接秒
代码
#include<iostream>
#include<vector>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<0)
{
putchar('-');
write(-x);
return;
}
if(x<10)
putchar(x%10+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
void write(long long x)
{
if(x<10)
putchar(x%10+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
}
namespace lst
{
struct tree
{
int l,r;
int lazy;
int val;
}tre[400005];
void push_down(int k)
{
tre[k<<1].lazy+=tre[k].lazy;
tre[k<<1|1].lazy+=tre[k].lazy;
tre[k<<1].val+=tre[k].lazy*(tre[k<<1].r-tre[k<<1].l+1);
tre[k<<1|1].val+=tre[k].lazy*(tre[k<<1|1].r-tre[k<<1|1].l+1);
tre[k].lazy=0;
}
void build(int l,int r,int k)
{
tre[k].l=l;
tre[k].r=r;
if(tre[k].l==tre[k].r)
return;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void change(int l,int r,int val,int k)
{
if(l>tre[k].r||tre[k].l>r)
return;
if(l<=tre[k].l&&tre[k].r<=r)
{
tre[k].val+=val*(tre[k].r-tre[k].l+1);
tre[k].lazy+=val;
return;
}
push_down(k);
change(l,r,val,k<<1);
change(l,r,val,k<<1|1);
tre[k].val=tre[k<<1].val+tre[k<<1|1].val;
}
int ask(int pos,int k)
{
if(tre[k].l>pos||pos>tre[k].r)
return 0;
if(tre[k].l==tre[k].r)
return tre[k].val;
push_down(k);
return ask(pos,k<<1)+ask(pos,k<<1|1);
}
}
using namespace lst;
using namespace IO;
struct node
{
int u,v,col;
}a[300005];
int n,m,cnt;
int opt,u,v;
int dfn[100005],l[100005],r[100005];
int dp_ind[100005][25],dep[100005];
vector<int> g[100005];
void dfs(int u,int fa)
{
dfn[u]=++cnt;
dep[u]=dep[fa]+1;
change(dfn[u],dfn[u],dep[u],1);
l[u]=r[u]=cnt;
for(int i=1;i<=20;i++)
dp_ind[u][i]=dp_ind[dp_ind[u][i-1]][i-1];
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa)
{
dp_ind[v][0]=u;
dfs(v,u);
l[u]=min(l[u],l[v]);
r[u]=max(r[u],r[v]);
}
}
}
pii lca(int u,int v)
{
pii t;
if(u==v)
return make_pair(u,0);
if(dep[u]>dep[v])
swap(u,v);
for(int i=20;i>=0;i--)
if(dep[u]<=dep[dp_ind[v][i]])
{
t.y+=(1<<i);
v=dp_ind[v][i];
}
if(u==v)
{
t.x=u;
return t;
}
for(int i=20;i>=0;i--)
{
if(dp_ind[u][i]!=dp_ind[v][i])
{
t.y+=(1<<(i+1));
u=dp_ind[u][i];
v=dp_ind[v][i];
}
}
t.y+=2;
t.x=dp_ind[u][0];
return t;
}
int main()
{
read(n);
build(1,n,1);
for(int i=1;i<n;i++)
{
read(a[i].u);
read(a[i].v);
g[a[i].u].push_back(a[i].v);
g[a[i].v].push_back(a[i].u);
a[i].col=1;
}
dfs(1,0);
for(int i=1;i<=n;i++)
if(dep[a[i].u]>dep[a[i].v])
swap(a[i].u,a[i].v);
read(m);
for(int i=1;i<=m;i++)
{
read(opt);
read(u);
if(opt==1)
{
if(a[u].col==0)
{
change(l[a[u].v],r[a[u].v],1,1);
a[u].col=1;
}
}
if(opt==2)
{
if(a[u].col==1)
{
change(l[a[u].v],r[a[u].v],-1,1);
a[u].col=0;
}
}
if(opt==3)
{
read(v);
pii t=lca(u,v);
if(ask(dfn[u],1)+ask(dfn[v],1)-2*ask(dfn[t.x],1)!=t.y)
write(-1);
else
write(t.y);
putchar('\n');
}
}
return 0;
}

浙公网安备 33010602011771号