zoukankan      html  css  js  c++  java
  • 刷题总结——寻宝游戏(bzoj3991 dfs序)

    题目:

    Description

     小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

    Input

     第一行,两个整数N、M,其中M为宝物的变动次数。

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

    Output

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

    Sample Input

    4 5
    1 2 30
    2 3 50
    2 4 60
    2
    3
    4
    2
    1

    Sample Output

    0
    100
    220
    220
    280

    HINT

     1<=N<=100000


    1<=M<=100000

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

    题解:

      本以为这是一道虚树题····然而并没有什么卵关系···

      考虑静态时求ans,肯定是将每个有宝藏的点按dfs序排个序···然后两两间求最短距离相加,最后再加上末首位的点的最短距离就可以了····相当于模拟走动的过程

      然而题目要加点和删点···直接用set求前驱后继维护ans就可以了···注意边界条件···

      md一个sbset题调了我一个上午···我可能是智障吧····注意set的end()返回的是迭代器最后的一个位置··这个位置并没有赋值···因此要求末位的点需要*--set.end();

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<set>
    using namespace std;
    set<int>st;
    set<int>:: iterator t;
    const int inf=0x3f3f3f3f;
    const int N=1e5+5;
    int first[N],go[N*2],next[N*2],val[N*2],tot,n,m,dfn[N],cnt,jud[N],id[N],deep[N],g[N][20];
    long long dis[N],ans;
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline void comb(int a,int b,int c)
    {
      next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;
      next[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c;
    }
    inline void dfs(int u,int fa)
    {
      dfn[u]=++cnt;id[cnt]=u;
      for(int e=first[u];e;e=next[e])
      {
        int v=go[e];if(v==fa)  continue;
        dis[v]=(long long)val[e]+dis[u];g[v][0]=u;deep[v]=deep[u]+1;
        dfs(v,u);
      }
    }
    inline int get(int a,int b)
    {
      if(deep[a]<deep[b])  swap(a,b);
      int i,j; 
      for(i=0;(1<<i)<=deep[a];i++);i--;
      for(j=i;j>=0;j--)
        if(deep[a]-(1<<j)>=deep[b])  a=g[a][j];
      if(a==b)  return a;
      for(i=17;i>=0;i--)
        if(g[a][i]!=g[b][i])
          a=g[a][i],b=g[b][i];
      return g[a][0];
    }
    inline long long Dis(int a,int b)
    {
      int lca=get(a,b);
      return dis[a]+dis[b]-dis[lca]*2;
    }
    inline int pre(int x)
    {
      t=st.find(dfn[x]);
      return t==st.begin()?0:id[*--t];
    }
    inline int nxt(int x)
    {
      t=st.find(dfn[x]);
      return ++t==st.end()?0:id[*t];
    }
    inline void Insert(int x)
    {
      st.insert(dfn[x]);
      int l=pre(x);int r=nxt(x);
      if(l)  ans+=Dis(l,x);
      if(r)  ans+=Dis(r,x);
      if(l&&r)  ans-=Dis(l,r);
    }
    inline void Delete(int x)
    {
      int l=pre(x);int r=nxt(x);
      if(l)  ans-=Dis(l,x);
      if(r)  ans-=Dis(r,x);
      if(l&&r)  ans+=Dis(l,r);
      st.erase(dfn[x]);
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      n=R(),m=R();int a,b,c;
      for(int i=1;i<n;i++)
      {
        a=R(),b=R(),c=R();
        comb(a,b,c);
      }
      deep[1]=1;dfs(1,0);
      for(int i=1;i<=17;i++)
        for(int j=1;j<=n;j++)
          g[j][i]=g[g[j][i-1]][i-1];
      while(m--)
      {
        a=R();jud[a]=(jud[a]+1)%2;
        if(jud[a])
          Insert(a);
        else
          Delete(a);
        printf("%lld
    ",st.size()?ans+Dis(id[*st.begin()],id[*--st.end()]):0);
      }
      return 0;
    }
     
  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/AseanA/p/7591210.html
Copyright © 2011-2022 走看看