BZOJ1095:[ZJOI2007]Hide 捉迷藏(动态点分治)
Description
捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。
Input
第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。
Output
对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。
Sample Input
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
3
3
4
HINT
对于100%的数据, N ≤100000, M ≤500000。
Solution
维护三个堆。
$h1[x]$存当前重心$x$管辖的范围内的点到$x$在点分树上的父亲的所有距离。
$h2[x]$存$x$在点分树上所有儿子的$h1$堆的堆顶。
$h3$存每个点的答案。
关灯的点$h2$自带一个$0$方便处理单链……
反正快退役了也不想写太多了……还有问题看代码吧……
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N (100009)
using namespace std; struct Heap
{
priority_queue<int>q,del;
void push(int x) {q.push(x);}
void erase(int x) {del.push(x);}
bool empty() {return q.size()-del.size()==;}
int size() {return q.size()-del.size();}
int top()
{
while (!del.empty() && q.top()==del.top()) q.pop(), del.pop();
return q.top();
}
void pop()
{
while (!del.empty() && q.top()==del.top()) q.pop(), del.pop();
return q.pop();
}
int sec()
{
if (size()<) return -;
int tmp1=top(); pop();
int tmp2=top(); push(tmp1);
return tmp2;
}
}h1[N],h2[N],h3; struct Edge{int to,next;}edge[N<<];
int n,m,root,sum,light_num;
int s[N],f[N][],fa[N],dep[N],maxsize[N],size[N],vis[N];
int head[N],num_edge; inline int read()
{
int x=,w=; char c=getchar();
while (c<'' || c>'') {if (c=='-') w=-; c=getchar();}
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x*w;
} void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void DFS(int x,int fa)
{
dep[x]=dep[fa]+; f[x][]=fa;
for (int i=; i<=; ++i) f[x][i]=f[f[x][i-]][i-];
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa) DFS(edge[i].to,x);
} void Get_Root(int x,int fa)
{
size[x]=; maxsize[x]=;
for (int i=head[x]; i; i=edge[i].next)
if (!vis[edge[i].to] && edge[i].to!=fa)
{
Get_Root(edge[i].to,x);
size[x]+=size[edge[i].to];
maxsize[x]=max(maxsize[x], size[edge[i].to]);
}
maxsize[x]=max(maxsize[x],sum-size[x]);
if (maxsize[x]<maxsize[root]) root=x;
} void Solve(int x)
{
vis[x]=;
for (int i=head[x]; i; i=edge[i].next)
if (!vis[edge[i].to])
{
sum=size[edge[i].to]; root=;
Get_Root(edge[i].to,x);
fa[root]=x; Solve(root);
}
} int LCA(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
for (int i=; i>=; --i)
if (dep[f[x][i]]>=dep[y]) x=f[x][i];
if (x==y) return x;
for (int i=; i>=; --i)
if (f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
return f[x][];
} void Insert(int x)
{
if (h2[x].size()>=)
h3.push(h2[x].top()+h2[x].sec());
} void Delete(int x)
{
if (h2[x].size()>=)
h3.erase(h2[x].top()+h2[x].sec());
} void Turn_off(int x)
{
Delete(x); h2[x].push(); Insert(x);
light_num--;
for (int t=x,ft=fa[t]; ft; t=fa[t],ft=fa[t])
{
Delete(ft);
if (!h1[t].empty()) h2[ft].erase(h1[t].top());
h1[t].push(dep[x]+dep[ft]-*dep[LCA(x,ft)]);
h2[ft].push(h1[t].top());
Insert(ft);
}
} void Turn_on(int x)
{
Delete(x); h2[x].erase(); Insert(x);
light_num++;
for (int t=x,ft=fa[t]; ft; t=fa[t],ft=fa[t])
{
Delete(ft);
if (!h1[t].empty()) h2[ft].erase(h1[t].top());
h1[t].erase(dep[x]+dep[ft]-*dep[LCA(x,ft)]);
if (!h1[t].empty()) h2[ft].push(h1[t].top());
Insert(ft);
}
} int main()
{
n=read(); sum=maxsize[]=n;
for (int i=; i<=n-; ++i)
{
int u=read(),v=read();
add(u,v); add(v,u);
}
DFS(,);
Get_Root(,);
Solve(root);
for (int i=; i<=n; ++i) Turn_off(i);
light_num=;
m=read();
while (m--)
{
char opt=getchar();
while (opt!='C' && opt!='G') opt=getchar();
if (opt=='C')
{
int x=read();
if (!s[x]) Turn_on(x);
else Turn_off(x);
s[x]^=;
}
else
{
if (light_num>=n-) puts(light_num==n?"-1":"");
else printf("%d\n",h3.top());
}
}
}
BZOJ1095:[ZJOI2007]Hide 捉迷藏(动态点分治)的更多相关文章
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...
- bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习
好迷啊...感觉动态点分治就是个玄学,蜜汁把树的深度缩到logn (静态)点分治大概是递归的时候分类讨论: 1.答案经过当前点,暴力(雾)算 2.答案不经过当前点,继续递归 由于原树可以长的奇形怪状( ...
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆
[BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...
- 【bzoj1095】[ZJOI2007]Hide 捉迷藏 动态点分治+堆
题目描述 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这 ...
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...
- BZOJ 1095 [ZJOI2007]Hide 捉迷藏 ——动态点分治
[题目分析] 这题好基啊. 先把分治树搞出来.然后每个节点两个堆. 第一个堆保存这个块里的所有点(即分治树中的所有儿子)到分治树上的父亲的距离. 第二个堆保存分治树子树中所有儿子第一个堆的最大值. 建 ...
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏(动态点分治)
传送门 解题思路 点分树其实就是在点分治的基础上,把重心连起来.这样树高是\(log\)的,可以套用数据结构进行操作.这道题是求最远距离,所以每个点维护两个堆,分别表示所管辖的子树的最远距离和到父节点 ...
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏 动态点分治+堆
写了7k多,可以说是一己之力切掉了这道毒瘤题~ 开 $3$ 种堆,分别维护每个子树最大深度,以及每个节点在点分树中对父亲的贡献,和全局的最优解. 由于需要支持堆的删除,所以写起来特别恶心+麻烦. 细节 ...
- 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏
简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...
随机推荐
- 【Linux】linux查看日志文件内容命令tail、cat、tac、head、echo
linux查看日志文件内容命令tail.cat.tac.head.echo tail -f test.log你会看到屏幕不断有内容被打印出来. 这时候中断第一个进程Ctrl-C, ---------- ...
- Html5、css、JavaScript基础
一.HTML学习 HTML样式Css 内联样式- 在HTML元素中使用"style" 属性 内部样式表 -在HTML文档头部 <head> 区域使用<style& ...
- 洛谷P3235 [HNOI2014]江南乐(Multi-SG)
题目描述 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F,然后游戏系统 ...
- Ubuntu快捷键、Ubuntu终端常用命令
Ubuntu快捷键 0.Ctrl + Alt + t 打开终端,在终端命令行操作 1. Ctrl + W: 关闭当前 Nautilus 窗口 2. Ctrl+T: 在 Nautilus 打开新的 Ta ...
- Android 彩色Toast实现
Android默认的Toast太丑了,我们来封装一个花里胡哨的Toast吧,就叫ColoredToast. Github:https://github.com/imcloudfloating/Desi ...
- Android IPC机制(三)使用AIDL实现跨进程方法调用
上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...
- LeetCode单排日记
初衷 之前有研究过一段时间数据结构与算法,但平时使用的不多,就连排序都很少用(自从JDK8有了Stream,就再也没有手写排序了.),所谓用进废退,时至今日,能记住的已经不多了,还记得之前有一次面试, ...
- Docker Data Center系列(五)- 使用自定义的TLS安全认证
本系列文章演示如何搭建一个mini的云平台和DevOps实践环境. 基于这套实践环境,可以部署微服务架构的应用栈,演练提升DevOps实践能力. 1 名词说明 CSR: Certificate Sig ...
- ES搜索引擎集群模式搭建【Kibana可视化】
一.简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎(与Solr类似),基于RESTful web接口.Elasticsearch是用Ja ...
- windows10 专业版的远程服务器管理工具下载
一.安装远程服务器管理工具: 下载地址: https://www.microsoft.com/zh-cn/download/details.aspx?id=45520 二.关闭远程服务器管理工具: 1 ...