在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想……

插入/删除一个新节点时就把其dfn插入set/从set中删除。

当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离。

比较显然?不会证明……

貌似叫“虚树”?

#include<cstdio>
#include<set>
using namespace std;
#define N 100001
typedef long long ll;
set<int>S;
typedef set<int>::iterator ER;
int n,m;
int v[N<<1],first[N],next[N<<1],w[N<<1],en;
void AddEdge(int U,int V,int W)
{
v[++en]=V;
w[en]=W;
next[en]=first[U];
first[U]=en;
}
int top[N],dep[N],fa[N],siz[N],son[N],dfn[N],Map[N];
ll sumv[N],ans;
bool a[N];
void dfs(int U)
{
siz[U]=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
fa[v[i]]=U;
dep[v[i]]=dep[U]+1;
sumv[v[i]]=sumv[U]+(ll)w[i];
dfs(v[i]);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void df2(int U)
{
dfn[U]=++en;
Map[en]=U;
if(son[U])
{
top[son[U]]=top[U];
df2(son[U]);
}
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U]&&v[i]!=son[U])
{
top[v[i]]=v[i];
df2(v[i]);
}
}
int 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])
swap(U,V);
return U;
}
ll Query(int U,int V)
{
return sumv[U]+sumv[V]-(sumv[lca(U,V)]<<1);
}
int main()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&x,&y,&z);
AddEdge(x,y,z);
AddEdge(y,x,z);
}
en=0;
top[1]=1;
dfs(1);
df2(1);
for(;m;--m)
{
scanf("%d",&x);
a[x]^=1;
if(a[x])
{
S.insert(dfn[x]);
ER it=S.end(); --it;
ER jt=S.begin();
if(S.size()==0||S.size()==1) ans=0;
if(S.size()==2)
ans=(Query(Map[*jt],Map[*it])<<1);
else if(S.size()>2&&(*jt)==dfn[x])
{
ans+=Query(Map[*jt],Map[*it]);
ER kt=jt; ++kt;
ans+=Query(Map[*jt],Map[*kt]);
ans-=Query(Map[*kt],Map[*it]);
}
else if(S.size()>2&&(*it)==dfn[x])
{
ans+=Query(Map[*jt],Map[*it]);
ER kt=it; --kt;
ans+=Query(Map[*it],Map[*kt]);
ans-=Query(Map[*kt],Map[*jt]);
}
else if(S.size()>2)
{
ER kt=S.find(dfn[x]);
ER lt=kt; --lt;
ER mt=kt; ++mt;
ans+=Query(Map[*lt],Map[*kt]);
ans+=Query(Map[*kt],Map[*mt]);
ans-=Query(Map[*lt],Map[*mt]);
}
}
else
{
ER it=S.end(); --it;
ER jt=S.begin();
if(S.size()==0||S.size()==1) ans=0;
if(S.size()==2)
ans=(Query(Map[*jt],Map[*it])<<1);
else if(S.size()>2&&(*jt)==dfn[x])
{
ans-=Query(Map[*jt],Map[*it]);
ER kt=jt; ++kt;
ans-=Query(Map[*jt],Map[*kt]);
ans+=Query(Map[*kt],Map[*it]);
}
else if(S.size()>2&&(*it)==dfn[x])
{
ans-=Query(Map[*jt],Map[*it]);
ER kt=it; --kt;
ans-=Query(Map[*it],Map[*kt]);
ans+=Query(Map[*kt],Map[*jt]);
}
else if(S.size()>2)
{
ER kt=S.find(dfn[x]);
ER lt=kt; --lt;
ER mt=kt; ++mt;
ans-=Query(Map[*lt],Map[*kt]);
ans-=Query(Map[*kt],Map[*mt]);
ans+=Query(Map[*lt],Map[*mt]);
}
S.erase(dfn[x]);
}
printf("%lld\n",ans);
}
return 0;
}

【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏的更多相关文章

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

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

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

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

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

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

  4. [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set

    寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...

  5. bzoj3991 [SDOI2015]寻宝游戏 树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...

  6. bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护

    之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...

  7. bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并

    题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...

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

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

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

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

随机推荐

  1. Mockito中@Mock与@InjectMock

    Mockito是java单元测试中,最常用的mck工具之一,提供了诸多打桩方法和注解.其中有两个比较常用的注解,@Mock和@InjectMock,名字和在代码中使用 的位置都很像,对于初学者,很容易 ...

  2. POJ3189:Steady Cow Assignment(二分+二分图多重匹配)

    Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7482   Accepted: ...

  3. Android推送使用--文章集锦

    Android之基于百度云推送IM Android实现推送方式解决方案 Android消息推送(一)--AndroidPn(XMPP协议)Demo版到正式上线 采用XMPP协议实现Android推送 ...

  4. 帮助小伙伴写的组装xml字符串类

    import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.uti ...

  5. Python基础(4)_集合、布尔类型

    一.集合 集合的作用一:关系运算集合的作用二:去重 定义集合:集合内的元素必须是唯一的:集合内的元素必须是可hash的,也是就不可变类型:集合是无序的 s={'egon',123,'egon','1' ...

  6. 【洛谷 P1364】医院设置(树的重心)

    树的重心的定义: 树若以某点为根,使得该树最大子树的结点数最小,那么这个点则为该树的重心,一棵树可能有多个重心. 树的重心的性质: 1.树上所有的点到树的重心的距离之和是最短的,如果有多个重心,那么总 ...

  7. Windows autoKeras的下载与安装连接

    autoKeras autoKeras GitHub:https://github.com/jhfjhfj1/autokeras 百度网盘下载地址:http://pandownload.com/ 大牛 ...

  8. SVN被锁定解决办法

    转自:https://blog.csdn.net/strwangfan/article/details/78748393: 今天用SVN的时候出现被锁定的情况,既不能更新代码也不能提交. 解决方法如下 ...

  9. 【 Python 】函数的参数

    一.默认参数: 默认参数可以简化函数的调用,设置默认参数时,有几点要注意: 1,必选参数在前,默认参数在后,否则python的解释器会报错. 2,如何设置默认参数. 当函数有多个参数时,把变化大的参数 ...

  10. lua返回服务器信息

    ngx.header.content_type = "text/plain"; ngx.say(tostring(ngx.var.request_uri));ngx.say(tos ...