• BZOJ 3991 set维护dfs序


    思路:
    set按照dfn排序
    两点之间的距离可以O(logn)算出来
    加一个点-> now
    ans+=dis(pre,now)+dis(now,next)-dis(pre-next);
    删一个点同理
    最后加上dis(begin,end)即可

    //By SiriusRen
    #include <set>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=200050;
    typedef long long ll;
    int first[N],next[N],v[N],w[N],tot,cnt,rev[N];
    int n,m,xx,yy,zz,dfn[N],deep[N],fa[N/2][20];
    ll ans,wei[N],temp;
    struct cmp{bool operator()(int x,int y){return dfn[x]<dfn[y];}};
    set<int,cmp>s;set<int,cmp>::iterator it,itpre,itnext;
    void add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs(int x){
        dfn[x]=++cnt;
        for(int i=first[x];~i;i=next[i])
            if(v[i]!=fa[x][0])
                deep[v[i]]=deep[x]+1,wei[v[i]]=wei[x]+w[i],fa[v[i]][0]=x,dfs(v[i]);
    }
    int lca(int x,int y){
        if(deep[x]<deep[y])swap(x,y);
        for(int i=19;i>=0;i--)if(deep[x]-(1<<i)>=deep[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    ll dis(int x,int y){return wei[x]+wei[y]-2*wei[lca(x,y)];}
    int main(){
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&xx,&yy,&zz);
            add(xx,yy,zz),add(yy,xx,zz);
        }
        dfs(1),deep[1]=1;
        for(int j=1;j<=19;j++)
            for(int i=1;i<=n;i++)
                fa[i][j]=fa[fa[i][j-1]][j-1];
        while(m--){
            scanf("%d",&xx);
            rev[xx]^=1;
            if(rev[xx]){
                s.insert(xx),it=s.lower_bound(xx);
                itnext=++it,--it;
                if(it!=s.begin())itpre=--it,++it,ans+=dis(*itpre,*it);
                if(itnext!=s.end())ans+=dis(*itnext,*it);
                if(it!=s.begin()&&itnext!=s.end())ans-=dis(*itpre,*itnext);
            }
            else{
                it=s.lower_bound(xx);
                itnext=++it,--it;
                if(it!=s.begin())itpre=--it,++it,ans-=dis(*itpre,*it);
                if(itnext!=s.end())ans-=dis(*itnext,*it);
                if(it!=s.begin()&&itnext!=s.end())ans+=dis(*itpre,*itnext);
                s.erase(it);
            }
            it=s.end();
            if(s.size()>1)temp=dis(*s.begin(),*(--it));
            else temp=0;
            printf("%lld
    ",ans+temp);
        }
    }

    这里写图片描述

  • 相关阅读:
    一个Work Stealing Pool线程池的实现
    一步一步解剖Libevent源代码
    一步一步学习堆排序算法
    一个通用的Makefile框架
    为什么我们知道那么多道理(理论),却依然处理不好目前的生活
    SQL
    走进Java Map家族 (1)
    Java数组协变与范型不变性
    尝鲜Java 12新特性:switch表达式
    android高级UI之PathMeasure<一>--Path测量基础(nextContour、getPosTan、getMatrix、getSegment)
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532016.html
Copyright © 2020-2023  润新知