在考试代码的基础上稍微改改就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. 解决IIS设置多个工作进程中Session失效的问题

    利用StateServer实现Session共享 session保存在专门的StateServer中,该种方式,性能损失比sql略好.比inproc据说有10%-15%的性能损失.怎么使用StateS ...

  2. HDU 2639 01背包求第k大

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. wyh的天鹅~vector的使用

    链接:https://www.nowcoder.com/acm/contest/93/L来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 262144K,其他语言52428 ...

  4. spring的普通类中如何取session和request对像

    在使用spring时,经常需要在普通类中获取session,request等对像. 比如一些AOP拦截器类,在有使用struts2时,因为struts2有一个接口使用org.apache.struts ...

  5. [BZOJ1010][HNOI2008]玩具装箱toy 解题报告

    Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...

  6. LeetCode 4 :Majority Element

    problem:Given an array of size n, find the majority element. The majority element is the element tha ...

  7. 转:在android中button响应的两种方式

    1. 在布局文件中添加button的监听名字 Android:onClick="buttonOnClick" 例如: <Button android:id="@+i ...

  8. rtp包格式

    转载一篇帮助我了解h264 rtp的文档,地址http://www.cppblog.com/czanyou/archive/2009/12/25/67940.html 当packetization-m ...

  9. Kuangbin 带你飞-线段树专题 题解

    HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include < ...

  10. Tarjan & LCA 套题题目题解

    刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <se ...