题目大意:

一颗树 有一个点的集合

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

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

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

思路:

对于每个集合

它的答案一定为从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. python019 Python3 File(文件) 方法

    file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 序号 方法及描述 1 file.close() 关闭文件.关闭后文件不能再进行读写操作. 2 file.flush() ...

  2. Leetcode 236.二叉树的最近公共祖先

    二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x ...

  3. Leetcode 221.最大的正方形

    最大的正方形 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出 ...

  4. UVA674-Coin Change,用动归思想来递推!

    674 - Coin Change 题意:有1分,5分,10分,25分,50分共5种硬币,数量不限.给你一个n求有多少种方法凑齐n,注意:d[0]=1; 思路:推了前几组样例,可以发现直接用当前状态累 ...

  5. [HDU5919]Sequence II

    [HDU5919]Sequence II 试题描述 Mr. Frog has an integer sequence of length n, which can be denoted as a1,a ...

  6. ubuntu使用git提交github时,执行pull或者push命令要重新输入用户名和密码

    ubuntu使用git提交github时,执行pull或者push命令要重新输入用户名和密码: 1:问题现象: hlp@hlp:~/code/github_code/catch_imooc1$ git ...

  7. CF788E:New task

    n个数字中,每个数有数字A和属性B,每次操作将某个点x的属性B改变为0或1,求满足这样要求的子序列的个数: 下标a<b<c<d<e,而Aa<=Ab=Ac=Ad>=A ...

  8. 解决Flex4在Module里调用PopUpManager报错问题

    项目大了 就需要用到Module, 发现在一个Module里边, 和普通应用里一样popup一个组件的时候, 总是会报错. 这个在Flex3的时候也会出现, 会报样式错误 所以就想到了addPopUp ...

  9. .htaccess重写、安全防护、文件访问权限

    今天在<外刊IT评论>上看见了关于.htaccess的使用总结,觉得很不错的,因为wp博客还有其他的php的web服务站点好多都是用.htaccess来管理比如效率以及安全的问题,有必要来 ...

  10. dsu on tree:关于一类无修改询问子树可合并问题

    dsu on tree:关于一类无修改询问子树可合并问题 开始学长讲课的时候听懂了但是后来忘掉了....最近又重新学了一遍 所谓\(dsu\ on\ tree\)就是处理本文标题:无修改询问子树可合并 ...