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层... 动态点分治:记录下每个重心的上一层重心,这 ...
随机推荐
- MyBatis:事务回滚
事务的隔离级别:DEFAULT.READ_UNCOMMITED.READ_COMMITTED.REPEATABLE_READ.SERIALIZABLE 事务的传播行为:REQUIRED.SUPPORT ...
- Less 结合 nth-child 选择器循环生成样式
问题描述: 实现头像的堆叠效果 从第二个头像开始,每个头像都会盖住前一个头像上,遮盖的宽度为 30px 实现叠加的方式有很多,比如给每个头像添加 translateX 属性,或者使用负值 margin ...
- babel在项目里的使用
1.手动在项目里创建文件 .babelrc 2.安装 $ npm install --save-dev babel-cli # ES2015转码规则 $ npm install --save-dev ...
- 关于相机拍照获取图片onActivityResult返回data 为null的问题
调用相机拍摄方法 /** * capture new image */ protected void selectPicFromCamera() { if (!EaseCommonUtils.isSd ...
- SQL 中事务的分类
先讲下事务执行流程: BEGIN和COMMIT PRINT @@TRANCOUNT --@@TRANCOUNT统计事务数量 BEGIN TRAN PRINT @@TRANCOUNT BEGIN TRA ...
- SQL语句(floor、ceiling和round以及left和right)
前言:个人认为命令没有必要记,学过的知识总结一下,用到了可以快速找到派上用场.用的多了,自然会记住,但是一定要理解每一个字符代表的是什么,多一个少一个会怎么样 要点概述 floor 和ceiling和 ...
- WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证
为什么还要写这类文章?因为我看过网上很多讲解的都不够全面,而本文结合实际工作讲解了swaggerui文档,统一响应格式,异常处理,权限验证等常用模块,并提供一套完善的案例源代码,在实际工作中可直接参考 ...
- ELK 处理 Percona 审计日志(填坑)
前提 1.有强烈的审计需求. 2.能允许10%-15%左右的性能损失. 3.有强烈的对数据库操作实时查看需求(一般都是为了领导要求). Logstash 比较坑的配置 1 2 3 4 5 6 7 ...
- c/c++ 友元的简单应用
友元的简单应用 1,对象 + 对象,或者,对象 + 数字,可以用类的成员函数去重载+号函数,但是,数字 + 对象就不能用类的成员函数去重载+号函数了, 因为编译器会把数字 + 对象翻译成数字.oper ...
- MapFileParser.sh: Permission denied
Unity项目,需要用Xcode运行,结果报了错误. 解决方案: 1.打开终端, 2.输入以下命令: chmod +x /Users/......./MapFileParser.sh (MapFi ...