zoukankan      html  css  js  c++  java
  • P3320 [SDOI2015]寻宝游戏 解题报告

    P3320 [SDOI2015]寻宝游戏

    题目描述

    小B最近正在玩一个寻宝游戏,这个游戏的地图中有(N)个村庄和(N-1)条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。

    小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小(B)需要不断地更新数据,但是小(B)太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

    输入输出格式

    输入格式:

    第一行,两个整数(N)(M),其中(M)为宝物的变动次数。接下来的(N-1)行,每行三个整数(x)(y)(z),表示村庄(x)(y)之间有一条长度为z的道路。接下来的(M)行,每行一个整数(t),表示一个宝物变动的操作。若该操作前村庄(t)内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

    输出格式:

    (M)行,每行一个整数,其中第(i)行的整数表示第(i)次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出(0)

    说明

    (1<=N<=100000)

    (1<=M<=100000)

    对于全部的数据,(1<=z<=10^9)


    首先发现似乎走两次,然而没啥用,然后yy一波,也没啥用。

    考虑走出了一个环,想想虚树的构建,如果按(dfs)序走这个环,那么就可以了。

    为什么呢,我只会意会...

    然后用(set)维护一下(dfs)序就行了,边界写起来怪麻烦的。


    Code:

    #include <cstdio>
    #include <set>
    #define ll long long
    const int N=1e5+10;
    int head[N],to[N<<1],Next[N<<1],edge[N<<1],cnt;
    void add(int u,int v,int w)
    {
        to[++cnt]=v,Next[cnt]=head[u],edge[cnt]=w,head[u]=cnt;
    }
    int dfn[N],f[N][18],dep[N],ha[N],dfsclock;
    ll dis[N];
    void dfs(int now)
    {
        dep[now]=dep[f[now][0]]+1;
        ha[dfn[now]=++dfsclock]=now;
        for(int i=1;f[now][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
        for(int v,i=head[now];i;i=Next[i])
            if((v=to[i])!=f[now][0])
                dis[v]=dis[now]+edge[i],f[v][0]=now,dfs(v);
    }
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y]) return LCA(y,x);
        for(int i=17;~i;i--)
            if(dep[f[x][i]]>=dep[y])
                x=f[x][i];
        if(x==y) return x;
        for(int i=17;~i;i--)
            if(f[x][i]!=f[y][i])
                x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    ll Dis(int x,int y){return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);}
    std::set <int> s;
    std::set <int>::iterator it;
    ll sum;int n,m,tag[N];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int u,v,w,i=1;i<n;i++) scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
        dfs(1);
        for(int t,i=1;i<=m;i++)
        {
            scanf("%d",&t);
            if(tag[t])//删
            {
                if(s.size()!=1)
                {
                    it=s.lower_bound(dfn[t]);
                    if(it==s.begin())
                    {
                        ++it;
                        sum-=Dis(t,ha[*it]);
                        sum-=Dis(t,ha[*--s.end()]);
                        sum+=Dis(ha[*it],ha[*--s.end()]);
                    }
                    else if(it==--s.end())
                    {
                        sum-=Dis(t,ha[*--it]);
                        sum-=Dis(t,ha[*s.begin()]);
                        sum+=Dis(ha[*it],ha[*s.begin()]);
                    }
                    else
                    {
                        int p=*--it;
                        sum-=Dis(t,ha[p]);
                        ++it,++it;
                        sum-=Dis(t,ha[*it]);
                        sum+=Dis(ha[p],ha[*it]);
                    }
                }
                s.erase(dfn[t]);
            }
            else
            {
                if(!s.empty())
                {
                    it=s.lower_bound(dfn[t]);
                    if(it==s.end())
                    {
                        sum+=Dis(t,ha[*--it]);
                        sum+=Dis(t,ha[*s.begin()]);
                        sum-=Dis(ha[*it],ha[*s.begin()]);
                    }
                    else if(it==s.begin())
                    {
                        sum+=Dis(t,ha[*it]);
                        sum+=Dis(t,ha[*--s.end()]);
                        sum-=Dis(ha[*it],ha[*--s.end()]);
                    }
                    else
                    {
                        int p=*it;
                        sum+=Dis(t,ha[p]);
                        --it;
                        sum+=Dis(t,ha[*it]);
                        sum-=Dis(ha[p],ha[*it]);
                    }
                }
                s.insert(dfn[t]);
            }
            tag[t]^=1;
            printf("%lld
    ",sum);
        }
        return 0;
    }
    

    2018.12.14

  • 相关阅读:
    CNN comprehension
    Gradient Descent
    Various Optimization Algorithms For Training Neural Network
    gerrit workflow
    jenkins job配置脚本化
    Jenkins pipeline jobs隐式传参
    make words counter for image with the help of paddlehub model
    make words counter for image with the help of paddlehub model
    git push and gerrit code review
    image similarity
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10121793.html
Copyright © 2011-2022 走看看