zoukankan      html  css  js  c++  java
  • 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);
        }
    }

    这里写图片描述

  • 相关阅读:
    Eclipse svn插件包
    最新版STS因为JDK版本太低无法启动的解决办法
    maven 项目无法发布,无法编译的解决办法
    maven依赖本地非repository中的jar包
    微信公众平台开发(2)-消息封装
    微信公众平台开发(4)-自定义菜单
    限制必须使用微信打开网页
    移动设备页面自适应
    微信公众平台开发(5)-上传下载多媒体文件
    微信公众平台开发(3)-回复消息
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532016.html
Copyright © 2011-2022 走看看