[bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set
寻宝游戏 bzoj-3991 SDOI-2015
题目大意:题目链接。
注释:略。
想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并。
树链的并的求法就是把所有点按照$dfs$序排序然后相加再减去相邻之间的$lca$。
故此我们按照$dfs$序维护一个平衡树。
每次往里插入节点即可。
实时用$lca$更新答案,复杂度$O(nlogn)$。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define N 100010
using namespace std; typedef long long ll;
set<int>s;
int head[N],nxt[N<<1],to[N<<1],tot; ll val[N<<1];
ll dis[N],ans; int dic[N],f[22][N],size[N],re[N],dep[N],cnt;
bool vis[N];
inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
ll rd() {ll x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
inline void add(int x,int y,ll z) {to[++tot]=y; val[tot]=z; nxt[tot]=head[x]; head[x]=tot;}
void dfs(int pos,int fa)
{
f[0][pos]=fa; for(int i=1;i<=20;i++) f[i][pos]=f[i-1][f[i-1][pos]];
dep[pos]=dep[fa]+1; dic[pos]=++cnt,re[cnt]=pos; size[pos]=1; for(int i=head[pos];i;i=nxt[i]) if(to[i]!=fa)
{
dis[to[i]]=dis[pos]+val[i]; dfs(to[i],pos); size[pos]+=size[to[i]];
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;~i;i--) if(dep[f[i][x]]>=dep[y]) x=f[i][x];
if(x==y) return x;
for(int i=20;~i;i--) if(f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
return f[0][x];
}
inline void output()
{
set<int>::iterator it=s.begin();
for(;it!=s.end();it++) printf("%d ",*it); puts("");
}
int main()
{
int n=rd(),m=rd(); for(int i=1;i<n;i++) {int x=rd(),y=rd(); ll z=rd(); add(x,y,z); add(y,x,z);}
dfs(1,1);
// for(int i=1;i<=n;i++) printf("%d %d %d %d %d %d\n",re[dic[i]],dis[i],dic[i],dep[i],size[i],f[0][i]);
for(int i=1;i<=m;i++)
{
int x=rd();
if(s.empty()) {s.insert(dic[x]),ans=dis[x]; vis[x]=true;}
else if(!vis[x])
{
vis[x]=true;
set<int>::iterator it1=s.lower_bound(dic[x]);
set<int>::iterator it2=s.upper_bound(dic[x]);
if(it2==s.end())
{
it1--;
ans+=dis[x]-dis[lca(x,re[*it1])];
}
else
{
if(it1==s.begin()) ans+=dis[x]-dis[lca(x,re[*it1])];
else
{
it1--;
int y=re[*it1],z=re[*it2];
ans+=dis[x]+dis[lca(y,z)]-dis[lca(x,y)]-dis[lca(x,z)];
}
}
s.insert(dic[x]);
}
else
{
vis[x]=false;
set<int>::iterator it1=s.lower_bound(dic[x]);
set<int>::iterator it2=s.upper_bound(dic[x]);
if(it2==s.end())
{
if(it1==s.begin()) ans=0;
else
{
it1--;
int y=re[*it1];
ans+=dis[lca(x,y)]-dis[x];
}
}
else
{
if(it1==s.begin())
{
int z=re[*it2];
ans+=dis[lca(x,z)]-dis[x];
}
else
{
it1--;
int y=re[*it1],z=re[*it2];
ans+=dis[lca(y,x)]+dis[lca(x,z)]-dis[x]-dis[lca(y,z)];
}
}
s.erase(dic[x]);
}
// output();
// cout << ans << endl ;
set<int>::iterator it1=s.begin();
set<int>::iterator it2=s.end();
if(it1==it2) puts("0");
else
{
it2--;
if(it1==it2) puts("0");
else printf("%lld\n",(ans-dis[lca(re[*it1],re[*it2])])*2);
}
}
return 0;
}
小结:好题啊好题啊。
[bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set的更多相关文章
- [BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...
- CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏
异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
- bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并
题目大意:支持多次操作,增加或删除一个关键点 动态维护虚树边权和*2 分析:可以用树链求并的方法,最后减去虚树的根到1距离 注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离 找df ...
- bzoj3991 [SDOI2015]寻宝游戏 树链的并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...
- BZOJ 3991: [SDOI2015]寻宝游戏 [虚树 树链的并 set]
传送门 题意: $n$个点的树,$m$次变动使得某个点有宝物或没宝物,询问每次变动后集齐所有宝物并返回原点的最小距离 转化成有根树,求树链的并... 两两树链求并就可以,但我们按照$dfs$序来两两求 ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- 【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set
[题意]给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回.现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价.n,m<=10^5. ...
- 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏
在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...
随机推荐
- IE8下ajax兼容问题
function crossDomainAjax(url, successCallback) { // IE8 & 9 only Cross domain JSON GET request i ...
- TCP协议三次握手和四次握手
前言 先说一下IP协议和TCP协议,IP协议是无连接的通信协议,IP不会占用两个设备之间通信的线路,IP实际上主要负责将每个数据包路由至目的地,但是IP协议并没有能够确保数据包是否到达,传过去的数据包 ...
- 用nowrap实现div内的元素不换行
在编写自定义插件my-slider的过程中,发现无论float还是inline-block均不能保证div内的内容不换行(这两个属性在内容超出容器尺寸后,均将剩余内容做换行处理),在浏览器内比较了自己 ...
- 转载:如何使用RFT自动打开IE
如何在RFT测试脚本中打开IE浏览器? 第一步,配置应用程序进行测试: “配置”菜单 ——> “配置应用程序进行测试...”,进入下面这个界面,默认三个自带的应用程序,点击“添加”加入IE. ...
- 遮罩 HUD 指示器 蒙板 弹窗
遮罩 HUD 指示器 蒙板 弹窗 UIAlertView的使用<代理方法处理按钮点击> UIAlertView *alertView = [[UIAlertView alloc] init ...
- 【Lucene】实现全文索引
2. Lucene 实现全文检索的流程2.1.索引和搜索流程图 绿色表示索引过程,对要搜索的原始内容进行索引构建一个索引库,索引过程包括:确定原始内容即要搜索的内容 -> 采集文档 -> ...
- 查看MySQL默认字符集
MySQL默认字符集相信大家都有所了解,下面就为您介绍一下查看MySQL默认字符集的命令,希望对您学习MySQL默认字符集能有些帮助. MySQL的字符集支持(Character Set Suppor ...
- April Fools Day Contest 2019: editorial回顾补题
A. Thanos Sort time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- 03C#数据类型
C#数据类型 值类型和引用类型区别 在C#语言中,值类型变量存储的是指定数据类型的数据,值类型变量的值(或实例)存储在栈(Stack)中,赋值语句是传递变量的值.引用类型(例如类就是引用类型)的实例, ...
- 时间戳显示格式为几天前、几分钟前、几秒前---vue过滤器
//时间显示问题(几天前.几分钟前)Vue.filter('fomatTime', function (valueTime) { if(valueTime){ var newData = Date.p ...