• bzoj 1095


    首先仍然是点对之间的问题,让我们考虑点分

    由于带修改,所以考虑动态点分治

    所谓动态点分治,就是在操作之前先模拟一遍点分治的过程构造出一棵新的树,我们称这棵树为点分树,由于这棵树树高是对数级别的,所以修改的时候可以在一条树链上暴力修改

    然后考虑本题怎么维护:

    首先我们考虑答案如何统计:在统计答案时,我们找出每个节点向其所有子树中最大的距离,然后计算这些最大深度的最大值+次大值,然后放进一个堆里维护即可

    为什么要放进堆里维护?

    因为还可能需要插入或删除嘛!

    这样的话,我们考虑怎么维护答案

    首先我们需要记录以一个点为根节点的子树中到这个点最深的深度,这一点比较好维护

    然后我们还需要记录以一个点为根节点子树中向上更新的最深的深度,这一点也比较容易维护

    (注意我们现在的树是点分树,但深度讨论的是原来的树!因此不能简单地传递!)

    接下来就是堆的删除和修改了

    有个小trick:开两个堆,如果需要删除的话推到另一个堆里,在查询时如果两堆堆顶相等就一起弹掉

    需要卡常,求LCA不妨用欧拉序

    贴代码:

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define uint unsigned int
    using namespace std;
    struct Edge
    {
        uint nxt;
        uint to;
    }edge[200005];
    struct Heap
    {
        priority_queue <uint> Q1,Q2;
        void push(uint x){Q1.push(x);}
        void del(uint x){Q2.push(x);}
        uint top()
        {
            while(!Q1.empty()&&!Q2.empty()&&Q1.top()==Q2.top())Q1.pop(),Q2.pop();
            if(!Q1.empty())return Q1.top();
            else return -1;
        }
        void pop()
        {
            while(!Q1.empty()&&!Q2.empty()&&Q1.top()==Q2.top())Q1.pop(),Q2.pop();
            if(!Q1.empty())Q1.pop();
        }
        bool empty(){return Q1.size()-Q2.size()==0;}
        uint size(){return Q1.size()-Q2.size();}
        uint sec()
        {
            if(Q1.size()-Q2.size()<=1)return -1;
            uint t=top();pop();
            uint ret=top();push(t);
            return ret;
        }
    }Q[100005][2],re;
    uint head[100005];
    uint siz[100005],maxp[100005];
    uint pre[100005],vis[100005];
    uint sit[100005];
    uint ttop[100005];
    uint lg2[500005];
    uint dep[100005];
    uint dfn[100005];
    uint rmq[500005][22];
    uint s,rt;
    uint t=0;
    uint cnt=1;
    uint n,m,s_lig;
    inline void add(uint l,uint r)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        head[l]=cnt++;
    }
    void dfs(uint x,uint fx)
    {
        dep[x]=dep[fx]+1,dfn[x]=++t;
        rmq[t][0]=x;
        for(register uint i=head[x];i;i=edge[i].nxt)
        {
            uint to=edge[i].to;
            if(to==fx)continue;
            dfs(to,x);
            rmq[++t][0]=x;
        }
    }
    /*void redfs(uint x,uint topx,uint fx)
    {
        ttop[x]=topx;
        if(son[x])redfs(son[x],topx,x);
        for(register uint i=head[x];i;i=edge[i].nxt)
        {
            uint to=edge[i].to;
            if(to==fx||to==son[x])continue;
            redfs(to,to,x);
        }
    }*/
    void get_f()
    {
        for(register uint j=1;j<=17;++j)
        {
            for(register uint i=1;i+(1<<j)-1<=t;++i)
            {
                rmq[i][j]=dep[rmq[i][j-1]]<dep[rmq[i+(1<<(j-1))][j-1]]?rmq[i][j-1]:rmq[i+(1<<(j-1))][j-1];
            }
        }
          for(register uint i=2;i<=t;i++)lg2[i]=lg2[i>>1]+1;
    }
    
    inline uint LCA(uint x,uint y)
    {
         int l=dfn[x],r=dfn[y];
             if(l>r)swap(l,r);         
             int lg=lg2[r-l+1];        
            return dep[rmq[l][lg]]<dep[rmq[r-(1<<lg)+1][lg]]?rmq[l][lg]:rmq[r-(1<<lg)+1][lg];
    }
    inline uint get_dis(uint x,uint y)
    {
        return dep[x]+dep[y]-2*dep[LCA(x,y)];
    }
    void get_rt(uint x,uint fx)
    {
        siz[x]=1,maxp[x]=0;
        for(register uint i=head[x];i;i=edge[i].nxt)
        {
            uint to=edge[i].to;
            if(to==fx||vis[to])continue;
            get_rt(to,x);
            siz[x]+=siz[to];
            maxp[x]=max(maxp[x],siz[to]);
        }
        maxp[x]=max(maxp[x],s-siz[x]);
        if(maxp[x]<maxp[rt])rt=x;
    }
    void solve(uint x)
    {
        vis[x]=1;
        for(register uint i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(vis[to])continue;
            s=siz[to],rt=0;
            get_rt(to,0);
            pre[rt]=x,solve(rt);
        }
    }
    void ins(uint x)
    {
        if(Q[x][1].size()>=2)re.push(Q[x][1].top()+Q[x][1].sec());
    }
    void del(uint x)
    {
        if(Q[x][1].size()>=2)re.del(Q[x][1].top()+Q[x][1].sec());
    }
    void turn_off(uint x)
    {
        del(x),Q[x][1].push(0),ins(x);
        s_lig--;
        for(uint i=x,pi=pre[x];pi;i=pi,pi=pre[i])
        {
            del(pi);
            if(!Q[i][0].empty())Q[pi][1].del(Q[i][0].top());
            Q[i][0].push(get_dis(x,pi));
            Q[pi][1].push(Q[i][0].top());
            ins(pi);
        }
    }
    void turn_on(uint x)
    {
        del(x),Q[x][1].del(0),ins(x);
        s_lig++;
        for(uint i=x,pi=pre[x];pi;i=pi,pi=pre[i])
        {
            del(pi);
            if(!Q[i][0].empty())Q[pi][1].del(Q[i][0].top());
            Q[i][0].del(get_dis(x,pi));
            if(!Q[i][0].empty())Q[pi][1].push(Q[i][0].top());
            ins(pi);
        }
    }
    inline uint read()
    {
        uint f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
        n=read();
        for(register uint i=1;i<n;++i)
        {
            uint x=read(),y=read();
            add(x,y),add(y,x);
        }
        rt=0,s=n,maxp[0]=0x3f3f3f3f;
        dfs(1,1),get_f(),get_rt(1,0),solve(rt);
        for(register uint i=1;i<=n;++i)turn_off(i);
        s_lig=0;
        m=read();
        while(m--)
        {
            char typ=getchar();
            while(typ!='C'&&typ!='G')typ=getchar();
            if(typ=='C')
            {
                uint x=read();
                if(sit[x])turn_off(x);
                else turn_on(x);
                sit[x]^=1;
            }else
            {
                if(s_lig==n)printf("-1
    ");
                else if(s_lig==n-1)printf("0
    ");
                else printf("%u
    ",re.top());
            }
        }
        return 0;
    }
  • 相关阅读:
    031.NET5_ActionFilter的自定义和执行特点
    030.NET5_Autofac单抽象多实现属性注入
    029.NET5_Autofac单抽象多实现构造函数注入
    028.NET5_Autofac通过类支持AOP
    vue 设置回车input提交
    vscode设置全局自动换行
    vscode 插件大全
    SQL Server 2019基础配置
    SQL Server 2019 安装教程
    phpstudy(php环境)设置内网访问
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11159702.html
Copyright © 2020-2023  润新知