题目链接:戳我

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

显然按照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. python 基础(十八)--shutil模块

    shutil模块 shutil.copyfileobj(src,dst):只拷贝文件内容,需要open文件:目标文件不存在时创建,存在时覆盖 shutil.copyfileobj(open('old. ...

  2. T100-----汇出EXCEL表格

    例子:cxmp541 #excel匯出功能 ON ACTION exporttoexcel LET g_action_choice="exporttoexcel" IF cl_au ...

  3. 佳能单反SDK 步骤

    EdsInitializeSDK(); EdsGetCameraList(&eclr);//获取相机列表 EdsGetChildCount(eclr, &camCount);  //获 ...

  4. 10 Django之Ajax请求

    一.什么是Ajax技术? 异步的JavaScript和XML.使用Javascript语言与服务器进行异步交互,传输的数据为XML(更多的使用json数据).Ajax不是一门新的编程语言,而是一种使用 ...

  5. vue 编译警告 Compiled with 4 warnings

    问题原因: windows下盘符的大小写导致的. 我在cmd里运行的时候,是切换到小写,改成大写的E盘符就没问题了

  6. VMwarevSphere Client 链接 vCenter Server中的主机,开启虚拟机提示:在主机当前连接状况下不允许执行该操作

    VMwarevSphere Client 链接 vCenter Server中的主机,开启虚拟机提示:在主机当前连接状况下不允许执行该操作很多原因都可以导致该问题出现,例如 vCenter Serve ...

  7. 【Day1】2.安装运行Python

     视频地址(全部) https://edu.csdn.net/course/detail/26057 课件地址(全部) https://download.csdn.net/download/gentl ...

  8. Delphi 卡通控件

    樊伟胜

  9. JDBC的两种sql命令发送器比较【Statement:PreparedStatement】

    PreparedStatement 接口继承 Statement接口如果需要多次执行一个SQL语句,可以使用PreparedStatement对象.在创建PreparedStatement对象时,通过 ...

  10. 关于php 7.4编译安装

    一个不错的文章 https://hqidi.com/150.html 贴个地址就好啦, 借鉴了一把,很良心