题目链接:戳我

可以知道,我们相当于是把有宝藏在的地方围了一个圈,求这个圈最小是多大。

显然按照dfs序来遍历是最小的。

那么我们就先来一遍dfs序列,并且预处理出来每个点到根的距离(这样我们就可用\(dis[u]+dis[v]-2*dis[lca(u,v)]\)来表示u,v之间的距离)

怎么动态维护这个东西呢?平衡树?不存在的,开一个set就行了。每次维护一下添加或者删除产生的影响就行了。

相似的题目是noi.ac#460 tree——

给你一棵n个点的树,每个点都有一个颜色ci。

有m次操作,每次操作会改变一个点的颜色或询问包含某个颜色的所有的点的最小联通块含有的边数。

最小连通块包含的边数,即该题的ans/2。而颜色的数量也不会对时间复杂度产生决定性影响。QAQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#include<algorithm>
#define MAXN 1000010
#define ll long long
using namespace std;
int n,m,t,tim;
int head[MAXN];
int dfn[MAXN],low[MAXN],son[MAXN],siz[MAXN],dep[MAXN],fa[MAXN],top[MAXN];
ll ans;
ll dis[MAXN];
set<int>s;
struct Edge{int nxt,to;ll dis;}edge[MAXN<<1];
inline void add(int from,int to,ll dis)
{
edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis;
head[from]=t;
}
inline void dfs1(int x,int pre)
{
siz[x]=1;
fa[x]=pre;
dep[x]=dep[pre]+1;
int maxx=-1;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==pre) continue;
dis[v]=dis[x]+edge[i].dis;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[v]>maxx) maxx=siz[v],son[x]=v;
}
}
inline void dfs2(int x,int topf)
{
top[x]=topf;
dfn[x]=++tim;
low[tim]=x;
if(son[x]) dfs2(son[x],topf);
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa[x]||v==son[x]) continue;
dfs2(v,v);
}
}
inline int get_lca(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
if(dep[u]<dep[v]) return u;
else return v;
}
inline ll get_dis(int u,int v){return dis[u]+dis[v]-2*dis[get_lca(u,v)];}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
dfs1(1,0);
dfs2(1,1);
// for(int i=1;i<=n;i++) printf("dis[%d]=%lld\n",i,dis[i]); puts("");
// for(int i=1;i<=n;i++) printf("dfn[%d]=%d\n",i,dfn[i]); puts("");
// for(int i=1;i<=n;i++) printf("low[%d]=%d\n",i,low[i]); puts("");
// for(int i=1;i<=n;i++) printf("dfn[%d]=%d\n",i,dfn[i]); puts("");
// for(int i=1;i<=n;i++) printf("low[%d]=%d\n",i,low[i]); puts("");
// for(int i=1;i<=n;i++)
// for(int j=i+1;j<=n;j++)
// printf("lca[%d %d]=%d\n",i,j,get_lca(i,j));
set<int>::iterator it,it1,it2;
while(m--)
{
int x;
scanf("%d",&x);
if(!s.count(dfn[x]))
{
s.insert(dfn[x]);
it=it1=it2=s.find(dfn[x]);
it1--,it2++;
if(it!=s.begin()) ans+=get_dis(x,low[*it1]);
if(it2!=s.end()) ans+=get_dis(x,low[*it2]);
if(it!=s.begin()&&it2!=s.end()) ans-=get_dis(low[*it1],low[*it2]);
}
else
{
it=it1=it2=s.find(dfn[x]);
it1--,it2++;
if(it!=s.begin()) ans-=get_dis(x,low[*it1]);
if(it2!=s.end()) ans-=get_dis(x,low[*it2]);
if(it!=s.begin()&&it2!=s.end()) ans+=get_dis(low[*it1],low[*it2]);
s.erase(dfn[x]);
}
if(s.size()<=1)
{
printf("0\n");
continue;
}
it=s.end();--it;
printf("%lld\n",ans+get_dis(low[*s.begin()],low[*it]));
}
return 0;
}

SDOI2015 寻宝游戏 | noi.ac#460 tree的更多相关文章

  1. [BZOJ3991][SDOI2015]寻宝游戏

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

  2. bzoj 3991: [SDOI2015]寻宝游戏 虚树 set

    目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...

  3. P3320 [SDOI2015]寻宝游戏 解题报告

    P3320 [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有\(N\)个村庄和\(N-1\)条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以 ...

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

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

  5. 3991: [SDOI2015]寻宝游戏

    3991: [SDOI2015]寻宝游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=3991 分析: 虚树+set. 要求树上许多点之间的路径的 ...

  6. 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

    [BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...

  7. P3320 [SDOI2015]寻宝游戏

    题目 P3320 [SDOI2015]寻宝游戏 做法 很巧妙的一种思路,懂了之后觉得大水题 首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历 那 ...

  8. CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏

    异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...

  9. [SDOI2015]寻宝游戏(LCA,set)

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

随机推荐

  1. Gson格式转换Integer变为Double类型问题解决

    问题描述 在前后端分离的开发模式下,前后端交互通常采用JSON格式数据.自然会涉及到json字符串与JAVA对象之间的转换.实现json字符串与Java对象相互转换的工具很多,常用的有Json.Gso ...

  2. Unknown custom element: <swiper>

    刚开始使用VUE,一直提示这个,后来才发现是注册组件时注册反了:先新建VUE实例再注册组件是问题根源,调转一下顺序即可解决

  3. 长沙理工大学第十二届ACM大赛-重现赛 大家一起来数二叉树吧 (组合计数)

    大意: 求n结点m叶子二叉树个数. 直接暴力, $dp[i][j][k][l]$表示第$i$层共$j$节点, 共$k$叶子, 第$i$层有$l$个叶子的方案数, 然后暴力枚举第$i$层出度为1和出度为 ...

  4. 牛客 40E 珂朵莉的数论题

    大意: 给定$x,y$, 求第$x$小的最小素因子为$y$的数, 若答案>1e9输出0. 若$y>=60$, 可以暴力筛出1e9/60以内的答案. 否则容斥+二分算出答案. #includ ...

  5. Navicat 12的安装与使用(附加破解)

    地址https://blog.csdn.net/tomos428/article/details/80483450?tdsourcetag=s_pctim_aiomsg

  6. whistle学习(一)之安装、使用、软件功能了解

    前言 whistle是基于Node实现的跨平台抓包调试代理工具,有以下基本功能: 查看HTTP.HTTPS请求响应内容 查看WebSocket.Socket收发的帧数据 设置请求hosts.上游htt ...

  7. O043、计算节点宕机了怎么办

    参考https://www.cnblogs.com/CloudMan6/p/5562131.html   Rebuild 可以恢复损坏的instance .那如果是宿主机坏了怎么办呢?比如硬件故障或者 ...

  8. 移动端h5+vue失焦搜索,ios和android兼容问题

    html部分: <input type="search" :placeholder="placeholder" v-model="searchN ...

  9. navicat连接阿里云mysql

    1.服务器控制台在安全组配置3306端口 2.进入 /etc/ssh/sshd_config 在最下面 加入下面代码 KexAlgorithms diffie-hellman-group1-sha1, ...

  10. 【转】awk学习笔记

    Awk学习笔记 整理:Jims of 肥肥世家 <jims.yang@gmail.com> Copyright © 2004 本文遵从GPL协议,欢迎转载.修改.散布. 第一次发布时间:2 ...