题目大意:

一颗树 有一个点的集合

对于每个集合的答案为 从集合内一个点遍历集合内所有点再返回的距离最小值

每次可以选择一个点 若在集合外便加入集合 若在集合内就删除

求每次操作后这个集合的答案

思路:

对于每个集合

它的答案一定为从dfs序最小的开始依次遍历再回来

当加入一个点x的时候 可以找到它dfs序的前驱与后继 画图可得 ans+=dis(pre,x)+dis(x,sub)-dis(pre,sub)  删除的时候为ans-=

特别地 当x没有前驱或后继时 前驱为最大值 后继为最小值(当做一个环

因此我们维护一颗平衡树搞一下即可

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#define inf 2139062143
#define ll long long
#define MAXN 100100
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int ch[MAXN][],fa[MAXN],sz,cnt[MAXN],val[MAXN],size[MAXN],rt;
int which(int x) {return x==ch[fa[x]][];}
int find_pre()
{
int pos=ch[rt][];
while(ch[pos][]) pos=ch[pos][];
return pos;
}
int find_max()
{
int pos=ch[rt][];
while(ch[pos][]) pos=ch[pos][];
return pos;
}
int find_min()
{
int pos=ch[rt][];
while(ch[pos][]) pos=ch[pos][];
return pos;
}
int find_sub()
{
int pos=ch[rt][];
while(ch[pos][]) pos=ch[pos][];
return pos;
}
void upd(int x)
{
if(!x) return ;
size[x]=cnt[x]+size[ch[x][]]+size[ch[x][]];
}
void rotate(int pos)
{
int f=fa[pos],ff=fa[f],k=which(pos);
ch[f][k]=ch[pos][k^],fa[ch[f][k]]=f,fa[f]=pos,ch[pos][k^]=f,fa[pos]=ff;
if(ff) ch[ff][ch[ff][]==f]=pos;
upd(f);upd(pos);
}
void splay(int x)
{
for(int f;f=fa[x];rotate(x))
if(fa[f]) rotate((which(x)==which(f)?f:x));
rt=x;
}
void Insert(int x)
{
int pos=rt,f=;
while()
{
if(val[pos]==x) {cnt[pos]++,upd(pos);upd(f);splay(pos);return ;}
f=pos,pos=ch[pos][x>val[pos]];
if(!pos)
{
ch[++sz][]=ch[sz][]=,fa[sz]=f,val[sz]=x,cnt[sz]=size[sz]=,ch[f][x>val[f]]=sz;
upd(f);splay(sz);return ;
}
}
}
void insert(int x)
{
if(!rt) {val[++sz]=x,ch[sz][]=ch[sz][]=fa[sz]=,cnt[sz]=size[sz]=,rt=sz;return;}
Insert(x);
}
int find_rank(int x)
{
int res=,pos=rt;
while()
{
if(x<val[pos]) pos=ch[pos][];
else
{
res+=size[ch[pos][]];
if(val[pos]==x) {splay(pos);return res+;}
res+=cnt[pos],pos=ch[pos][];
}
}
}
void dlt(int x)
{
if(cnt[rt]>) {cnt[rt]--;return ;}
if(!ch[rt][]&&!ch[rt][]) {rt=;return ;}
if(!ch[rt][]||!ch[rt][])
{
int k=!ch[rt][]?:;
rt=ch[rt][k],fa[rt]=;
return ;
}
int k=find_pre(),tmp=rt;
splay(k);fa[ch[tmp][]]=rt;
ch[rt][]=ch[tmp][],rt=k;
}
int n,m,nxt[MAXN<<],fst[MAXN],to[MAXN<<],Val[MAXN<<],Cnt;
int f[MAXN][],dep[MAXN],s[MAXN],k[MAXN],tot,hsh[MAXN],HSH[MAXN],vis[MAXN];
ll ans,dis[MAXN];
void add(int u,int v,int w) {nxt[++Cnt]=fst[u],fst[u]=Cnt,to[Cnt]=v,Val[Cnt]=w;}
void dfs(int x)
{
for(int i=;(<<i)<=dep[x];i++) f[x][i]=f[f[x][i-]][i-];
hsh[x]=++tot,HSH[tot]=x;
for(int i=fst[x];i;i=nxt[i])
if(to[i]!=f[x][])
{
dis[to[i]]=dis[x]+Val[i],dep[to[i]]=dep[x]+;
f[to[i]][]=x;dfs(to[i]);
}
}
int lca(int u,int v)
{
int t;
if(dep[u]<dep[v]) swap(u,v);
t=dep[u]-dep[v];
for(int i=;i<;i++)
if((<<i)&t) u=f[u][i];
if(u==v) return u;
for(int i=;i>=;i--)
if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
return f[u][];
}
inline ll calc(int u,int v) {return dis[HSH[u]]+dis[HSH[v]]-(dis[lca(HSH[u],HSH[v])]<<);}
int main()
{
n=read(),m=read();int a,b,c;
for(int i=;i<n;i++) {a=read(),b=read(),c=read();add(a,b,c);add(b,a,c);}
dfs();
while(m--)
{
c=hsh[read()],vis[c]^=;
if(vis[c])
{
if(!rt) {puts("");insert(c);continue;}insert(c);
a=val[find_pre()],b=val[find_sub()];
if(!a) a=val[find_max()];if(!b) b=val[find_min()];
if(!a) a=val[rt];if(!b) b=val[rt];
ans+=calc(a,c)+calc(b,c)-calc(a,b);
}
else
{
a=find_rank(c);
a=val[find_pre()],b=val[find_sub()];
if(!a) a=val[find_max()];if(!b) b=val[find_min()];
if(!a) a=val[rt];if(!b) b=val[rt];
ans-=calc(a,c)+calc(b,c)-calc(a,b);
dlt(c);
}
printf("%lld\n",ans);
}
}

bzoj 3991 寻宝游戏的更多相关文章

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

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

  2. 【BZOJ】【3991】【SDOI2015】寻宝游戏

    dfs序 我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ 而且苦逼的写的比正解还长……我骗点分容易吗QAQ 骗分做法: 1.$n,m\leq 1000$: ...

  3. 树形结构的维护:BZOJ 3991: [SDOI2015]寻宝游戏

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

  4. bzoj 3991: [SDOI2015]寻宝游戏

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

  5. 寻宝游戏(bzoj 3991)

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

  6. BZOJ 3991: [SDOI2015]寻宝游戏 树链的并+set

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

  7. [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)

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

  8. BZOJ.5285.[AHOI/HNOI2018]寻宝游戏(思路 按位计算 基数排序..)

    BZOJ LOJ 洛谷 话说vae去年的专辑就叫寻宝游戏诶 只有我去搜Mystery Hunt和infinite corridor了吗... 同样按位考虑,假设\(m=1\). 我们要在一堆\(01\ ...

  9. 3991: [SDOI2015]寻宝游戏

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

随机推荐

  1. XV6陷入,中断和驱动程序

    陷入,中断和驱动程序 运行进程时,cpu 一直处于一个大循环中:取指,更新 PC,执行,取指…….但有些情况下用户程序需要进入内核,而不是执行下一条用户指令.这些情况包括设备信号的发出.用户程序的非法 ...

  2. Python高级进阶(一)Python框架之Django入门

    传说中的Django Django由来 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的框架模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下 ...

  3. hihocoder 1165 : 益智游戏

    时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 幽香今天心情不错,正在和花田里的虫子玩一个益智游戏.这个游戏是这样的,对于一个数组A,幽香从A中选择一个数a,虫子从A中选 ...

  4. [Bzoj4832][Lydsy2017年4月月赛]抵制克苏恩 (期望dp)

    4832: [Lydsy2017年4月月赛]抵制克苏恩 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 673  Solved: 261[Submit][ ...

  5. Wannafly挑战赛4

    A(枚举) =w= B(枚举) 分析: 枚举每一位,考虑每位贡献,就是相当于在一段区间内找有多少1在奇数位上,有多少个1在偶数位上,维护一下各自前缀和就行了 时间复杂度O(32n) C(签到) D(d ...

  6. Eclipse-Java代码规范和质量检查插件-Checkstyle

    CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具.它能够自动化代码规范检查过程,从而使得开发人员从这项重要但枯燥的任务中解脱出来.它可以根 ...

  7. Java8初体验(二)Stream语法详解(转)

    本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...

  8. HDU 4115 Eliminate the Conflict(2-sat)

    HDU 4115 Eliminate the Conflict pid=4115">题目链接 题意:Alice和Bob这对狗男女在玩剪刀石头布.已知Bob每轮要出什么,然后Bob给Al ...

  9. poj 1695 Magazine Delivery 记忆化搜索

    dp[a][b][c],表示三个人从小到大依次在a,b.c位置时.距离结束最少的时间. 每次选一个人走到c+1位置搜索就好了. 坑点在于不能floyd.预计题目没说清楚.意思就是假设没送Li,那么Li ...

  10. 关于对FLASH开发,starling、starling feathers、starling MVC框架的理解

    说在前头:楼主之前没有不论什么flash开发经验,仅仅是从一次尝试中总结自己的理解和经验而已.假设有写的不正确的地方,欢迎大家指正. 前一段时间尝试想用flash(as3)又一次制作一下之前做的一个游 ...