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

题目链接

S T L STL STL坑害了一个晚上,真的菜的没救了啊。

准确的说是一个叫 r e v e r s e   i t e r a t o r reverse\ iterator reverse iterator的东西,就是我们经常用的 r b e g i n ( ) rbegin() rbegin()

有一个非常重要的性质

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

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

而不是一些别的东西


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

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

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

不过需要注意的是。

r b e g i n ( ) rbegin() rbegin()的问题!!!!!!!!!!!!!!

直接给代码了

#include
#include
#include
#include
#include
#include
#include
#include
#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:"<
     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<<"\n";
    continue;
     }
   int pre = getpre(dfn[x]); 
   //cout<<1<
     int last = getlas(dfn[x]);
    // cout<<"meiyou:"<
     ans=ans-getdis(pre,last);
  ans=ans+getdis(pre,x)+getdis(last,x);
     s.insert(dfn[x]);
     tag[x]=1;
  }
  cout<<ans<<"\n";
  }
  return 0;
}

你可能感兴趣的:(STL,平衡树)