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

  • 相关阅读:
    Ubuntu18.04安装RTX2080Ti+NVIDIA驱动+CUDA
    G++ 编译多个源文件
    线段树【递归版本】
    Linux 安装 python 指定版本--编译源码方式
    正则表达式高级替换
    【转载】Git忽略规则和.gitignore规则不生效的解决办法
    一次“惊险”的系统修复过程
    YOLO模型对图片中车辆的识别比对
    YOLOv3模型识别车位图片的测试报告(节选)
    在windows下用python调用darknet的yolo接口
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10121793.html
Copyright © 2011-2022 走看看