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

8
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

4
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 捉迷藏(动态点分治)的更多相关文章

  1. BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...

  2. bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习

    好迷啊...感觉动态点分治就是个玄学,蜜汁把树的深度缩到logn (静态)点分治大概是递归的时候分类讨论: 1.答案经过当前点,暴力(雾)算 2.答案不经过当前点,继续递归 由于原树可以长的奇形怪状( ...

  3. 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆

    [BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...

  4. 【bzoj1095】[ZJOI2007]Hide 捉迷藏 动态点分治+堆

    题目描述 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这 ...

  5. 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)

    题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...

  6. BZOJ 1095 [ZJOI2007]Hide 捉迷藏 ——动态点分治

    [题目分析] 这题好基啊. 先把分治树搞出来.然后每个节点两个堆. 第一个堆保存这个块里的所有点(即分治树中的所有儿子)到分治树上的父亲的距离. 第二个堆保存分治树子树中所有儿子第一个堆的最大值. 建 ...

  7. BZOJ 1095: [ZJOI2007]Hide 捉迷藏(动态点分治)

    传送门 解题思路 点分树其实就是在点分治的基础上,把重心连起来.这样树高是\(log\)的,可以套用数据结构进行操作.这道题是求最远距离,所以每个点维护两个堆,分别表示所管辖的子树的最远距离和到父节点 ...

  8. BZOJ 1095: [ZJOI2007]Hide 捉迷藏 动态点分治+堆

    写了7k多,可以说是一己之力切掉了这道毒瘤题~ 开 $3$ 种堆,分别维护每个子树最大深度,以及每个节点在点分树中对父亲的贡献,和全局的最优解. 由于需要支持堆的删除,所以写起来特别恶心+麻烦. 细节 ...

  9. 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏

    简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...

随机推荐

  1. nginx 日子配置

    nginx access_log nginx 日志说明 不同用户防卫Nginx会把每个用户访问往咱的日志信息记录到指定的日志文件里,供网站管理员分析用户浏览行为等,此功能又ngx_http_log_m ...

  2. 数据库索引(Oracle和Mysql)学习总结

    旭日Follow_24 的CSDN 博客 ,全文地址请点击: https://mp.csdn.net/postedit/80910082 索引概念:     索引是关系数据库中用于存放每一条记录的一种 ...

  3. Java并发编程-看懂AQS的前世今生

    在具备了volatile.CAS和模板方法设计模式的知识之后,我们可以来深入学习下AbstractQueuedSynchronizer(AQS),本文主要想从AQS的产生背景.设计和结构.源代码实现及 ...

  4. JavaScript中8个常见的陷阱

    译者按: 漫漫编程路,总有一些坑让你泪流满面. 原文: Who said javascript was easy ? 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版权归原 ...

  5. Angular6+ng-zorro实现登录页面

    一.效果图 二.html代码 <div class="login-container"> <div class="login-box"> ...

  6. CSS-水平和垂直居中

    div中水平和垂直居中 width:200px;height:200px; /*设置div的大小*/ border:1px solid green; /*边框*/ text-align: center ...

  7. java 不使用paint方法进行画图

    private Graphics2D g; g = (Graphics2D) getGraphics();

  8. python timeit模块简单用法

    timeit模块提供了一种简便的方法来为Python中的小块代码进行计时. 模块调用函数,stmp为要测试的函数,setup为测试环境,number为运行次数 timeit.timeit(stmt=) ...

  9. Spring入门详细教程(一)

    一.spring概述 Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于2003 年兴起的一个轻量级的 ...

  10. 洗礼灵魂,修炼python(68)--爬虫篇—番外篇之webbrowser模块

    题外话: 爬虫学到这里,我想你大部分的网站已经不再话下了对吧?有检测报文头的,我们可以伪造报文头为浏览器,有检测IP,我们可以用代理IP,有检测请求速度的,我们可以用time模块停顿一下,需要登录验证 ...