• 【BZOJ3991】寻宝游戏(SDOI2015)-贪心+DFS序+set


    测试地址:寻宝游戏
    做法:本题需要用到DFS+set。
    首先需要看出,无论从哪个点出发结果都相同。然后就是要找一种能得到最优解的走法,显然走每条边2次是最优的,那怎么样构造出走法呢?其实只要按照这些点的DFS序顺序走下去,最后走回第一个点即可。因为对于涉及到的每条边,只下去一次再上来一次,所以这个肯定最优。那么我们每次插入或删除一个点时,实际上只影响到它在DFS序中相邻的两个点之间的贡献,那么就用新的贡献替换旧的贡献,因为要求两点间的距离,用倍增求出即可。至于找到在当前点集中DFS序相邻的点,可以用set的lower_bound和upper_bound函数解决。
    学了这么久C++,居然现在才会用set,除了常数大一点还真是好用啊……
    以下是本人代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int n,m,first[100010]={0},tot=0,fa[100010][21],dep[100010];
    int pos[100010],r[100010],tim=0;
    ll dis[100010];
    set<int> S;
    set<int>::iterator it=S.begin();
    struct edge {int v,next;ll w;} e[200010];
    bool vis[100010]={0};
    
    void insert(int a,int b,ll w)
    {
        e[++tot].v=b,e[tot].w=w,e[tot].next=first[a],first[a]=tot;
    }
    
    void dfs(int v)
    {
        pos[v]=++tim;
        r[tim]=v;
        for(int i=first[v];i;i=e[i].next)
            if (e[i].v!=fa[v][0])
            {
                dep[e[i].v]=dep[v]+1;
                fa[e[i].v][0]=v;
                dis[e[i].v]=dis[v]+e[i].w;
                dfs(e[i].v);
            }
    }
    
    void findlr(int x,int &l,int &r)
    {
        it=S.lower_bound(x);
        if (it==S.begin()) it=S.end(),it--;
        else it--;
        l=*it;
        it=S.upper_bound(x);
        if (it==S.end()) it=S.begin();
        r=*it;
    }
    
    int lca(int x,int y)
    {
        if (dep[x]<dep[y]) swap(x,y);
        for(int i=20;i>=0;i--)
            if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
        if (x==y) return x;
        for(int i=20;i>=0;i--)
            if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            int x,y;
            ll z;
            scanf("%d%d%lld",&x,&y,&z);
            insert(x,y,z),insert(y,x,z);
        }
    
        fa[1][0]=dep[1]=0;dep[0]=-1;
        dfs(1);
        for(int i=1;i<=20;i++)
            for(int j=1;j<=n;j++)
                fa[j][i]=fa[fa[j][i-1]][i-1];
    
        ll ans=0;
        for(int i=1;i<=m;i++)
        {
            int x,px,py,g;
            scanf("%d",&x);
            if (!vis[x])
            {
                vis[x]=1;
                S.insert(pos[x]);
                findlr(pos[x],px,py);
                ans-=dis[r[px]]+dis[r[py]]-(dis[lca(r[px],r[py])]<<1);
                ans+=dis[r[px]]+dis[x]-(dis[lca(r[px],x)]<<1);
                ans+=dis[r[py]]+dis[x]-(dis[lca(r[py],x)]<<1);
            }
            else
            {
                vis[x]=0;
                findlr(pos[x],px,py);
                ans+=dis[r[px]]+dis[r[py]]-(dis[lca(r[px],r[py])]<<1);
                ans-=dis[r[px]]+dis[x]-(dis[lca(r[px],x)]<<1);
                ans-=dis[r[py]]+dis[x]-(dis[lca(r[py],x)]<<1);
                S.erase(pos[x]);
            }
            printf("%lld
    ",ans);
        }
    
        return 0;
    }
  • 相关阅读:
    在WIN10下搭建Robot Framework环境
    Robot Framework导入selenium2library库不成功的解决方法
    git命令大全
    Axure RP 8过期,用户名和序列号(注册码)
    MySQL用命令行快速导出数据备份
    JMeter—正则表达式提取器
    用JMeter进行接口测试
    d3-project
    bower 问题
    andriod studio
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793506.html
Copyright © 2020-2023  润新知