• 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)


    (STL)坑害了一个晚上,真的菜的没救了啊。

    准确的说是一个叫(reverse iterator)的东西,就是我们经常用的(rbegin())

    有一个非常重要的性质

    在反向迭代器中,++相当于正常的--,--相当于正常的++

    也就是说
    假设我们要访问(set)中的倒数第二个元素,我们要(++s.rbegin())

    而不是一些别的东西


    我们回到这个题,对于这个题目来说,其实我的第一反应是虚树,QWQ但事实证明,并不能用虚树来解决这个问题。

    我们可以通过一些方式,发现,无论从哪个有宝藏的点出发,访问所有点的总距离都是一定的。那么我们可以强制按照(dfn)顺序,每个点从(dfn)的上一个节点走过来,然后走向(dfn)的下一个节点,那么删除的之后,我们要是知道每个点的前驱和后继的话,就可以考虑直接更新(ans)了,(但是要特判第一个点和最后一个点,第一个点的前驱是最后一个点,最后一个点的后继是第一个点)

    那么既然需要一个排序+前驱后继的数据结构,自然就是(set)

    不过需要注意的是。

    (rbegin())的问题!!!!!!!!!!!!!!

    直接给代码了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define mk makr_pair
    #define ll long long
    #define int long long
    using namespace std;
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    const int maxn = 2e5+1e2;
    const int maxm = 2*maxn;
    const int inf = 1e9;
    int point[maxn],nxt[maxm],to[maxm];
    int cnt,n,m;
    int dfn[maxn],deep[maxn],f[maxn][21];
    set<int> s;
    int tot;
    int dis[maxn];
    int mp[maxn];
    int ans;
    int val[maxm],tag[maxn];
    void addedge(int x,int y,int w)
    {
     nxt[++cnt]=point[x];
     to[cnt]=y;
     val[cnt]=w;
     point[x]=cnt;
    }
    void dfs(int x,int fa,int dep)
    {
       deep[x]=dep;
       dfn[x]=++tot;
       mp[tot]=x;
       for (int i=point[x];i;i=nxt[i])
       {
         int p = to[i];
         if (p==fa) continue;
        f[p][0]=x;
        dis[p]=dis[x]+val[i];
      dfs(p,x,dep+1);
       } 
    }
    void init()
    {
     for (int j=1;j<=20;j++)
       for (int i=1;i<=n;i++)
         f[i][j]=f[f[i][j-1]][j-1];
    }
    int go_up(int x,int d)
    {
     for (int i=0;i<=20;i++)
       if ((1<<i) & d) x=f[x][i];
     return x;
    }
    int lca(int x,int y)
    {
     if (deep[x]>deep[y]) x=go_up(x,deep[x]-deep[y]);
     else y=go_up(y,deep[y]-deep[x]);
     if (x==y) return x;
     for (int i=20;i>=0;i--)
     {
      if (f[x][i]!=f[y][i])
      {
       x=f[x][i];
       y=f[y][i];
      }
     }
     return f[x][0];
    }
    int getdis(int x,int y)
    {
     return dis[x]-2*dis[lca(x,y)]+dis[y];
    }
    int getpre(int x)
    {
     set<int> :: iterator it = s.lower_bound(x);
     --it;
     if ((*it)==-inf) return mp[*(++s.rbegin())];
     else return mp[(*it)];
    }
    int getlas(int x)
    {
     set<int> :: iterator it = s.upper_bound(x);
     if ((*it)==inf) return mp[*(++s.begin())];
     else return mp[(*it)];
    }
    signed main()
    {
      //freopen("game.in.txt","r",stdin);
      //freopen("game.out","w",stdout);
      n=read();m=read();
      for (int i=1;i<n;i++)
      {
        int x=read(),y=read(),w=read();
        addedge(x,y,w);
        addedge(y,x,w);
      }
      dfs(1,0,1);
      init();
      s.insert(inf);
      s.insert(-inf);
      for (int i=1;i<=m;i++)
      {
        int x=read();
        if (tag[x])
        {
         int pre = getpre(dfn[x]);
         int last = getlas(dfn[x]);
        // cout<<"you:"<<pre<<" "<<last<<endl;
         ans=ans-getdis(pre,x)-getdis(last,x);
         ans=ans+getdis(pre,last);
         s.erase(dfn[x]);
         tag[x]=0;
      }
      else
      {
       if (s.size()==2) 
      {
        s.insert(dfn[x]);
        tag[x]=1;
        cout<<ans<<"
    ";
        continue;
         }
       int pre = getpre(dfn[x]); 
       //cout<<1<<endl; 
         int last = getlas(dfn[x]);
        // cout<<"meiyou:"<<pre<<" "<<last<<" "<<getdis(pre,x)<<" "<<lca(pre,x)<<" "<<dis[pre]<<" "<<dis[x]<<endl;
         ans=ans-getdis(pre,last);
      ans=ans+getdis(pre,x)+getdis(last,x);
         s.insert(dfn[x]);
         tag[x]=1;
      }
      cout<<ans<<"
    ";
      }
      return 0;
    }
    
    
  • 相关阅读:
    为 ADO 程序员设计的 ADO.NET (转)
    MSN 历史纪录分页显示(XML + XSL + Javascript)
    python连接postgresql数据库
    centOS安装scikitlearn
    14. 页高速缓存 20100228 21:10 322人阅读 评论(0) 收藏
    18. 程序的执行 20100302 12:56 131人阅读 评论(0) 收藏
    ttt 20110118 11:49 71人阅读 评论(0) 收藏
    15. 访问文件 20100228 22:55 129人阅读 评论(0) 收藏
    17. 进程间通信 20100302 12:49 191人阅读 评论(0) 收藏
    19(终). 系统启动 20100302 13:00 191人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161533.html
Copyright © 2020-2023  润新知