SDOI2015 寻宝游戏 | noi.ac#460 tree
题目链接:戳我
可以知道,我们相当于是把有宝藏在的地方围了一个圈,求这个圈最小是多大。
显然按照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的更多相关文章
- [BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
- P3320 [SDOI2015]寻宝游戏 解题报告
P3320 [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有\(N\)个村庄和\(N-1\)条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以 ...
- 【LG3320】[SDOI2015]寻宝游戏
[LG3320][SDOI2015]寻宝游戏 题面 洛谷 题解 不需要建虚树的虚树2333... 贪心地想一下,起始节点肯定是在关键点上,访问顺序就是\(dfs\)序. 那么对于每次询问, \[ An ...
- 3991: [SDOI2015]寻宝游戏
3991: [SDOI2015]寻宝游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=3991 分析: 虚树+set. 要求树上许多点之间的路径的 ...
- 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set
[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...
- P3320 [SDOI2015]寻宝游戏
题目 P3320 [SDOI2015]寻宝游戏 做法 很巧妙的一种思路,懂了之后觉得大水题 首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历 那 ...
- CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏
异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...
- [SDOI2015]寻宝游戏(LCA,set)
[SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到 ...
随机推荐
- JavaWeb应用系统开发实训任务(一)
项目描述: 随着家长对孩子教育的日渐重视,社区幼儿学校在国内逐渐兴起,对社区幼儿学校的信息化管理成为迫切需求.社区幼儿学校管理系统需要实现以下功能: 1) 教师管理:实现对教师信息的查询.删除.增加 ...
- Codeforces 1239C. Queue in the Train
传送门 事实上就是模拟 搞一个优先队列维护一下事件结构体:时间,人的编号,入队还是出队 再维护两个 $set$ ,队列内的人 $inQueue$ ,想要进入队列内的人 $want$ 然后模拟模拟模拟! ...
- SQL SERVER 语法
1.获取所有用户名: Select name FROM Sysusers where status='2' and islogin='1' islogin='1' :表示帐户 islogin='0' ...
- O063、NFS Volume Provider(Part II)
参考https://www.cnblogs.com/CloudMan6/p/5693771.html 本节开始创建 NFS volume ,操作方法和 LVM volume一样,唯一的区别是在 v ...
- vue打包后css背景图片地址找不到
背景图片变成了这样:static/css/static/imgs/xxx.jpg 解决方法,修改build/utils,添加 publicPath: '../../' 就行 对比了下,com ...
- 在webstorm中编译less,以及压缩css
一.编译 在全局安装less npm install -g less 在webstorm setting ->tools -> filewatcher中设置 : ../css/$Fi ...
- shell脚本视频学习1
一.知识点:变量,参数传递 练习1:使用shell脚本,输出当前所在的目录 练习2:计算/etc目录下有多少个文件,用shell脚本实现 ls -l--->数一下, ls -l|wc -l ( ...
- 【异常】The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
1 详细异常信息 The last packet sent successfully to the server was milliseconds ago. The driver has not re ...
- C库函数——字符串转数字整理
atof(将字符串转换成浮点型数)atoi(将字符串转换成整型数)atol(将字符串转换成长整型数)strtod(将字符串转换成浮点数)strtol(将字符串转换成长整型数)strtoul(将字符串转 ...
- 论文笔记:Unsupervised Domain Adaptation by Backpropagation
14年9月份挂出来的文章,基本思想就是用对抗训练的方法来学习domain invariant的特征表示.方法也很只管,在网络的某一层特征之后接一个判别网络,负责预测特征所属的domain,而后特征提取 ...