zoukankan      html  css  js  c++  java
  • bzoj3991: [SDOI2015]寻宝游戏

    思路:将关键点按dfs序排序,然后显然就是dfs序中相邻的两个点的距离之和加上最后一个点到第一点的距离(YY一下很显然),动态维护就用splay就好了(我是一个不会用set的蒟蒻。。。。。)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define maxn 100005
     
    int n,m,tot,deg,l,cnt;
    int now[maxn],pre[2*maxn],son[2*maxn],val[2*maxn],dep[maxn],dfn[maxn];
    int f[maxn][21];
    long long ans,dis[maxn];
    bool bo[maxn];
     
    inline int read(){
        int x=0;char ch=getchar();
        for (;ch<'0'||ch>'9';ch=getchar());
        for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
        return x;
    }
     
    void add(int a,int b,int c){
        son[++tot]=b;
        pre[tot]=now[a];
        now[a]=tot;
        val[tot]=c;
    }
     
    void link(int a,int b,int c){
        add(a,b,c),add(b,a,c);
    }
     
    void dfs(int x,int fa){
        dep[x]=dep[fa]+1,dfn[x]=++deg;
        for (int i=1;i<=l;i++) f[x][i]=f[f[x][i-1]][i-1];
        for (int p=now[x];p;p=pre[p])
            if (son[p]!=fa) f[son[p]][0]=x,dis[son[p]]=dis[x]+val[p],dfs(son[p],x);
    }
     
    int lca(int a,int b){
        if (dep[a]<dep[b]) swap(a,b);int x=dep[a]-dep[b],t=0;
        for (;x;x>>=1,t++) if (x&1) a=f[a][t];
        if (a==b) return a;t=l;
        for (;f[a][0]!=f[b][0];){
            for (;f[a][t]==f[b][t];t--);
            a=f[a][t],b=f[b][t];
        }
        return f[a][0];
    }
     
    struct splay_tree{
        int ch[maxn][2],fa[maxn],note[maxn],val[maxn],pos[maxn],root,tot;
        void rotate(int x){
            int y=fa[x],z=fa[y],bo=note[x],bo1=note[y];
            ch[y][bo]=ch[x][bo^1],fa[ch[x][bo^1]]=y;
            ch[x][bo^1]=y,fa[y]=x;
            fa[x]=z;if (bo1!=2) ch[z][bo1]=x;
            note[x]=bo1,note[y]=bo^1,note[ch[y][bo]]=bo;
        }
        void splay(int x){
            while (note[x]!=2){
                if (note[x]==note[fa[x]]) rotate(fa[x]);
                rotate(x);
            }
            root=x;
        }
        void insert(int x,int v,int p){
            int y;
            while (1){
                y=ch[x][val[x]<v];
                if (!y){
                    y=++tot;
                    val[y]=v,pos[y]=p;
                    if (x) note[y]=val[x]<v;else note[y]=2;
                    fa[y]=x,ch[y][0]=ch[y][1]=0;
                    if (x) ch[x][note[y]]=y;
                    break;
                }
                x=y;
            }
            splay(y);
        }
        int find(int v){
            int x=root;
            while (1){
                if (val[x]==v) return splay(x),x;
                if (val[x]<v) x=ch[x][1];else x=ch[x][0];
            }
        }
        int pre(int x){
            splay(x);x=ch[x][0];
            while (ch[x][1]) x=ch[x][1];
            return x;
        }
        int suc(int x){
            splay(x);x=ch[x][1];
            while (ch[x][0]) x=ch[x][0];
            return x;
        }
        int getmin(){int x=root;while (ch[x][0]) x=ch[x][0];return x;}
        int getmax(){int x=root;while (ch[x][1]) x=ch[x][1];return x;}
        void del(int v){
            int x=find(v);int y=suc(x),z=ch[x][0];
            if (!y){
                if (!z){root=0;return;}
                fa[z]=0,note[z]=2,root=z;return;
            }
            fa[ch[x][1]]=0,note[ch[x][1]]=2,splay(y);
            fa[z]=y,ch[y][0]=z,root=y;
        }
    }S;
     
    int main(){
        n=read(),m=read();l=log2(n);
        for (int i=1,a,b,c;i<n;i++) a=read(),b=read(),c=read(),link(a,b,c);
        dfs(1,0);
        while (m--){
            int x=read();bo[x]^=1;
            if (bo[x]) S.insert(S.root,dfn[x],x),cnt++;
            int a=S.pre(S.find(dfn[x])),b=S.suc(S.find(dfn[x]));
            if (!a) a=S.getmax();if (!b) b=S.getmin();
            a=S.pos[a],b=S.pos[b];
            if (!bo[x]) S.del(dfn[x]),cnt--;
            if (cnt<=1){puts("0"),ans=0;continue;}
            ans+=(bo[x]?1:-1)*(dis[a]+dis[x]-2*dis[lca(a,x)]);
            ans+=(bo[x]?1:-1)*(dis[x]+dis[b]-2*dis[lca(b,x)]);
            ans+=(bo[x]?-1:1)*(dis[a]+dis[b]-2*dis[lca(a,b)]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    生成指定规模大小的redis cluster对关系
    根据ip列表模拟输出redis cluster的主从对应关系
    获取redis实例绑定cpu的情况
    通过shell模拟redis-trib.rb info的输出
    又一种获取redis cluster slots分布的小脚本
    第3种方法获取redis cluster主从关系
    Lamada
    Linq笔记
    推荐博文
    SQL server 自带存储过程 sp_rename
  • 原文地址:https://www.cnblogs.com/DUXT/p/5993739.html
Copyright © 2011-2022 走看看