习题: 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;
}
posted @ 2020-08-24 10:53  loney_s  阅读(149)  评论(0)    收藏  举报