[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上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...
随机推荐
- AJPFX:如何保证对象唯一性呢?
思想: 1,不让其他程序创建该类对象. 2,在本类中创建一个本类对象. 3,对外提供方法,让其他程序获取这个对象. 步骤: 1,因为创建对象都需要构造函数初始化,只要将本类中的构造函数私有化,其他程序 ...
- Swift 基础语法入门(一)
一.变量和常量 1.声明常量和变量 用let来声明常量 let radius = 10 用var来声明变量 var age = 20 或者是var x = 0.0, y = 0.0, z = 0 ...
- Rxjava2的学习与总结
博客地址:https://luhaoaimama1.github.io/2017/07/31/rxjava/
- Objective - c Foundation 框架详解2
Objective - c Foundation 框架详解2 Collection Agency Cocoa provides a number of collection classes such ...
- 一致性hash学习
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单哈 ...
- 观锁和乐观锁——《POJOs in Action》
1 事务隔离 事务隔离是数据库提供的功能. SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别: SET TRANSACTION ...
- AIX6.1平台11.2.0.3RAC 实施手册
1 前言 此文档详细描述了Oracle 11gR2 数据库在AIX6.1上的安装RAC的检查及安装步骤.文档中#表示root用户执行,$表示grid或oracle用户执行. 2 系统环境 操作系统环境 ...
- 说说windows10自带浏览器Edge的好与不好
用了10几个月了,正式版也升级了,今天来说说微软自带浏览器microsoft Edge的好与不好 先说好的吧 一,浏览器速度非常快,无论是打开还是关闭,或者是语音助手小娜需要调动浏 ...
- 第2节 mapreduce深入学习:16、17、map端的join算法的实现
map端的join算法,适用于小表join大表的时候,一次性把小表的数据全部装载到内存当中来: 代码: MapJoinMain: package cn.itcast.demo5.mapJoin; im ...
- IIS启用32位应用程序兼容
针对服务器出现html和jsp页面都可以应用,但唯独asp页面打不开的一种情况 win7的IIS运行在32状态下,原因是ASP程序必须在32位下才能使用ACCESS 设置办法: 打开IIS管理器,点应 ...