被\(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<<"\n";
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<<"\n";
}
return 0;
}

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

  1. [洛谷P3320] SDOI2015 寻宝游戏

    问题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的 ...

  2. [bzoj3991] [洛谷P3320] [SDOI2015] 寻宝游戏

    Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有 \(N\) 个村庄和 \(N-1\) 条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬 ...

  3. 洛谷 P3320 [SDOI2015]寻宝游戏

    因为寻宝路径是一个环,所以寻宝花费的最小时间与起点无关.宝应当按照所有宝藏所在位置的 dfs 序进行才能够使得花费的时间最短.设 \(dist_i\) 表示 \(i\) 到树根的最短距离,那么树上任意 ...

  4. BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】

    题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...

  5. Luogu 3320 [SDOI2015]寻宝游戏

    一开始还真没想到. 发现从所有有宝藏的点出发绕一圈只要不刻意绕路答案都是一样的,即我们呢要求的最后答案$ans = dis(x_1, x_2) + dis(x_2, x_3) +... + dis(x ...

  6. 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)

    P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...

  7. [Bzoj3991]寻宝游戏(dfs序+set)

    Description 题目链接 Solution 用set按dfs序维护当前的宝物序列,那么答案为相邻2个点的距离加上头尾2个的距离 Code #include <cstdio> #in ...

  8. 洛谷 p1123 取数游戏【dfs】

    题目链接:https://www.luogu.org/problemnew/show/P1123 转载于:>>>>>> 题目描述 一个N×M的由非负整数构成的数字矩 ...

  9. 【LG3320】[SDOI2015]寻宝游戏

    [LG3320][SDOI2015]寻宝游戏 题面 洛谷 题解 不需要建虚树的虚树2333... 贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序. 那么对于每次询问, \[ An ...

随机推荐

  1. 机器学习基本概念:batch_size、epoch、 iteration

    batch_size 单次训练用的样本数,通常为2^N,如32.64.128... 相对于正常数据集,如果过小,训练数据就收敛困难:过大,虽然相对处理速度加快,但所需内存容量增加. 使用中需要根据计算 ...

  2. 使用 antd 的 form 组件来自定义提交的数据格式

    最近使用antd UI 的表单提交数据,数据里面有的是数组,有的是对象.提交的时候还要去校验参数,让人非常头疼.在我仔细看完文档之后,发现 antd 的 form 组件做的非常不错,这些需求通通不是问 ...

  3. volatile的基本原理

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...

  4. freeswitch的event事件处理

    概述 之前的文章中,我们讲解了freeswitch的源码基本结构,如何新增一个插件式模块,以及如何在模块中新增一个命令式API接口和APP接口. freeswitch本身是事件驱动的,它可以并发响应多 ...

  5. hibernate关联关系(一对多)

    什么是关联(association)关联指的是类之间的引用关系.如果类A与类B关联,那么被引用的类B将被定义为类A的属性.例如: class B{ private String name; } pub ...

  6. Struts2 的 OGNL

    ONGL简介: OGNL 的全称是对象图导航语言( Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存 ...

  7. noip模拟测试50

    考试过程:开题顺序1,2,3,做T1的时候我想到了要求的东西,就是分成尽量少的段使得每段之和>=k,但是我不会求,就打了个暴力走了,然后看T2,这题我觉得和之前做过的一道题比较像,因为我觉得\( ...

  8. 专项测试-App性能分析

    专项测试 app性能 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRece ...

  9. Vue+element基本增删改查

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  10. vue 输入框内容控制

    只能输入数字 <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model.number="a" ...