洛谷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<<"\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序)(反向迭代器的注意事项!)的更多相关文章
- [洛谷P3320] SDOI2015 寻宝游戏
问题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的 ...
- [bzoj3991] [洛谷P3320] [SDOI2015] 寻宝游戏
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有 \(N\) 个村庄和 \(N-1\) 条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬 ...
- 洛谷 P3320 [SDOI2015]寻宝游戏
因为寻宝路径是一个环,所以寻宝花费的最小时间与起点无关.宝应当按照所有宝藏所在位置的 dfs 序进行才能够使得花费的时间最短.设 \(dist_i\) 表示 \(i\) 到树根的最短距离,那么树上任意 ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- Luogu 3320 [SDOI2015]寻宝游戏
一开始还真没想到. 发现从所有有宝藏的点出发绕一圈只要不刻意绕路答案都是一样的,即我们呢要求的最后答案$ans = dis(x_1, x_2) + dis(x_2, x_3) +... + dis(x ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- [Bzoj3991]寻宝游戏(dfs序+set)
Description 题目链接 Solution 用set按dfs序维护当前的宝物序列,那么答案为相邻2个点的距离加上头尾2个的距离 Code #include <cstdio> #in ...
- 洛谷 p1123 取数游戏【dfs】
题目链接:https://www.luogu.org/problemnew/show/P1123 转载于:>>>>>> 题目描述 一个N×M的由非负整数构成的数字矩 ...
- 【LG3320】[SDOI2015]寻宝游戏
[LG3320][SDOI2015]寻宝游戏 题面 洛谷 题解 不需要建虚树的虚树2333... 贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序. 那么对于每次询问, \[ An ...
随机推荐
- git《一》
org.eclipse.jgit.api.errors.TransportException: https://gitee.com/wbweb/springboot_vue.git: Authenti ...
- Docker容器编排工具——docker-compose
1.docker-compose介绍 2.使用的三个步骤 3.安装docker-compose yum install docker-compose 4.docker-compose.yml 文件 ( ...
- 《DotNet Web应用单文件部署系列》二、打包wwwroot文件夹
在这篇文章中,你将学到web缓存规则,文件传输中用到的压缩格式,以及如何手写代码响应请求.最后还能学到快速打包wwwroot文件夹组件用法. 一.了解Response Header 当第一次加载程序时 ...
- openwrt开发笔记二:树莓派刷openwrt
前言及准备 本笔记适用于第一次给树莓派刷openwrt系统的玩家,对刷机过程及注意事项进行了记录,刷机之后对openwrt进行一些简单配置. 使用openwrt源码制作固件需要花费一点时间. 平台环境 ...
- Git 学习路线
前言 感觉 Git 还是很重要,应该单独开一篇文章来讲 Git... 使用系列教程 Git 系列教程(1)- Git 简介 Git 系列教程(2)- Git 安装 Git 系列教程(3)- 初次运行 ...
- Abp Vnext3 vue-admin-template(二用户退出)
先修改用户退出,中午有点困先改简单的 退出代码在src\layout\components\Navbar.vue代码如下,讲流程这里不需要修改 methods: { toggleSideBar() { ...
- Redis-初见
目录 启动and连接 JRedis 宝塔 Redis.conf RDB AOF(Append Only File) 发布和订阅 主从复制 一主二从 复制原理 宕机后的手动配置主机 哨兵模式 Redis ...
- Java学习笔记--注解和反射
注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...
- systemctl添加自定义系统服务
[Service] Type=forking ExecStart=绝对路径 ExecStop=绝对路径 ExecReload=绝对路径 以上最精简版,文件/usr/lib/systemd/system ...
- Linux上合理设置网卡的MTU值
MTU:是网络的最大传输单元,通信术语:最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位).最大传输单元这个 ...