BZOJ 1095: [ZJOI2007]Hide 捉迷藏(动态点分治)
解题思路
点分树其实就是在点分治的基础上,把重心连起来。这样树高是$log$的,可以套用数据结构进行操作。这道题是求最远距离,所以每个点维护两个堆,分别表示所管辖的子树的最远距离和到父节点的距离,再维护一个全局堆表示答案。修改的时候就从这个点开始暴力往上跳,每次修改到父节点的距离从而影响其父节点的子树的距离。时间复杂度$O(nlog^2n)$
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
const int N=100005;
inline int rd(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x;
}
void out(int x){
if(!x) return ;out(x/10);putchar('0'+x%10);
}
inline int max(int x,int y){return x>y?x:y;}
int n,head[N],cnt,to[N<<1],nxt[N<<1],Min,siz[N],m;
int dep[N],g[N][25],fa[N],Sum,rt,tot;
bool vis[N],open[N];
struct Heap{
priority_queue<int> del,Q;
inline void Push(int x) {Q.push(x);}
inline void Del(int x) {del.push(x);}
inline int Top(){
while(del.size() && Q.top()==del.top())
del.pop(),Q.pop();
return Q.top();
}
inline void Pop(){
while(del.size() && Q.top()==del.top())
del.pop(),Q.pop();
Q.pop();
}
inline int sec_Top(){
int tmp=Top(); Pop();
int ret=Top(); Push(tmp);
return ret;
}
inline int size(){return Q.size()-del.size();}
}f[N],c[N],ans;
inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
int top[N],son[N],Fa[N];
void dfs(int x,int F){
siz[x]=1; Fa[x]=F; int u,maxson=-1;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==F) continue;
dep[u]=dep[x]+1; dfs(u,x); siz[x]+=siz[u];
if(siz[u]>maxson) maxson=siz[u],son[x]=u;
}
}
void dfs2(int x,int topf){
top[x]=topf;if(!son[x]) return ;
dfs2(son[x],topf);int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==Fa[x] || u==son[x]) continue;
dfs2(u,u);
}
}
inline void init(){
n=rd();int x,y;
for(int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y); add(y,x);
}
dfs(1,0); dfs2(1,1);
}
void dfs1(int x,int F){
siz[x]=1; int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(vis[u] || u==F) continue;
dfs1(u,x); siz[x]+=siz[u];
}
}
inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]]) x=Fa[top[x]];
else y=Fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
inline int DIS(int x,int y){
if(!x || !y) return 0;
int lca=LCA(x,y);
return dep[x]+dep[y]-2*dep[lca];
}
void get_rt(int x,int F){
int Max=0,u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==F || vis[u]) continue;
get_rt(u,x); Max=max(Max,siz[u]);
}
Max=max(Max,Sum-siz[x]);
if(Max<Min) {Min=Max;rt=x;}
}
inline void get_dis(int x,int F,int pre){
f[pre].Push(DIS(fa[pre],x));
for(int i=head[x];i;i=nxt[i]){
int u=to[i]; if(vis[u] || u==F) continue;
get_dis(u,x,pre);
}
}
inline void Insert(Heap &x){
if(x.size()>1) ans.Push(x.Top()+x.sec_Top());
}
inline void Erase(Heap &x){
if(x.size()>1) ans.Del(x.Top()+x.sec_Top());
}
int DFS(int x,int F){
dfs1(x,0); Sum=siz[x]; Min=Sum+1; get_rt(x,0);
int G=rt,son; fa[G]=F; vis[G]=1; Sum=0;
get_dis(G,0,G); c[G].Push(0); rt=0;
for(register int i=head[G];i;i=nxt[i]){
int u=to[i]; if(vis[u]) continue;
son=DFS(u,G); c[G].Push(f[son].Top());
}
Insert(c[G]);
return G;
}
inline void solve_open(int x){
Erase(c[x]); c[x].Del(0); Insert(c[x]);
for(register int y=x;fa[y];y=fa[y]){
Erase(c[fa[y]]);
c[fa[y]].Del(f[y].Top());
f[y].Del(DIS(x,fa[y]));
if(f[y].size()) c[fa[y]].Push(f[y].Top());
Insert(c[fa[y]]);
}
}
inline void solve_close(int x){
Erase(c[x]); c[x].Push(0); Insert(c[x]);
for(register int y=x;fa[y];y=fa[y]){
Erase(c[fa[y]]);
if(f[y].size()) c[fa[y]].Del(f[y].Top());
f[y].Push(DIS(x,fa[y]));
c[fa[y]].Push(f[y].Top());
Insert(c[fa[y]]);
}
}
inline void work(){
char c=getchar();while(c!='C' && c!='G') c=getchar();
if(c=='G') {
if(tot<=1) printf("%d\n",tot-1);
else out(ans.Top()),putchar('\n');
}
else {
int x=rd();
if(!open[x]) tot--,solve_open(x),open[x]=1;
else tot++,solve_close(x),open[x]=0;
}
}
int main(){
init(); DFS(1,0); m=rd(); tot=n;
while(m--) work();
return 0;
}
BZOJ 1095: [ZJOI2007]Hide 捉迷藏(动态点分治)的更多相关文章
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...
- BZOJ 1095 [ZJOI2007]Hide 捉迷藏 ——动态点分治
[题目分析] 这题好基啊. 先把分治树搞出来.然后每个节点两个堆. 第一个堆保存这个块里的所有点(即分治树中的所有儿子)到分治树上的父亲的距离. 第二个堆保存分治树子树中所有儿子第一个堆的最大值. 建 ...
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏 动态点分治+堆
写了7k多,可以说是一己之力切掉了这道毒瘤题~ 开 $3$ 种堆,分别维护每个子树最大深度,以及每个节点在点分树中对父亲的贡献,和全局的最优解. 由于需要支持堆的删除,所以写起来特别恶心+麻烦. 细节 ...
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆
[BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...
- 【bzoj1095】[ZJOI2007]Hide 捉迷藏 动态点分治+堆
题目描述 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这 ...
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏
Description 一棵树,支持两个操作,修改一个点的颜色,问树上最远的两个白点距离. Sol 动态点分治. 动态点分治就是将每个重心连接起来,形成一个跟线段树类似的结构,当然它不是二叉的... ...
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...
- bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习
好迷啊...感觉动态点分治就是个玄学,蜜汁把树的深度缩到logn (静态)点分治大概是递归的时候分类讨论: 1.答案经过当前点,暴力(雾)算 2.答案不经过当前点,继续递归 由于原树可以长的奇形怪状( ...
- 【刷题】BZOJ 1095 [ZJOI2007]Hide 捉迷藏
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
随机推荐
- node连接mysql数据库
1. 创建项目,安装mysql 创建项目文件夹test, 在test文件夹下yarn add mysql --save安装mysql: 2. node使用mysql 在test文件夹下,创建test. ...
- Security基础(三):OpenSSL及证书服务、邮件TLS/SSL加密通信
一.OpenSSL及证书服务 目标: 本案例要求熟悉OpenSSL工具的基本使用,完成以下任务操作: 使用OpenSSL加密/解密文件 搭建企业自有的CA服务器,为颁发数字证书提供基础环境 方案: 使 ...
- supermarket
题目链接 题意:给你n个商品,商品的利润和商品的过期时间,商品必须在过期时间内卖才能算利润,每天只能卖一件商品,问利润最大值. 思路:用并查集+贪心的思路,先给商品从大到小排序,然后选择过期时间的根节 ...
- [CSP-S模拟测试]:antipalindrome(数学)
题目传送门(内部题58) 输入格式 第一行一个数$T$表示数据组数.接下来每行两个数$n$和$m$. 输出格式 $T$行,每行一个答案,对${10}^9+7$取模. 样例 样例输入: 25 66 5 ...
- bug 自定义的json2bean的bug
bug 在json2bean中如果不进行转换 if(bean instanceof HttpLogin){,将调用的市父类的Json2Meß 此并非最好的解决办法,应该用官方的json.toobje ...
- 北风设计模式课程---外观模式(Facade)总结
北风设计模式课程---外观模式(Facade)总结 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 设计模式都是对生活的抽象,比如用户获得装备,我可以先装备 ...
- 异常的处理try-catch
Java异常处理 Java采用的异常处理机制,是将异常处理的程序代码集中在一起, 与正常的程序代码分开,使得程序简洁.优雅,并易于维护. * 异常的处理: 抓抛模型*** 过程一 : 抛, 程序在执行 ...
- 让Tomcat支持php
在服务器上php的安装:1.下载php-4.4.2 for windows的压缩包2.解压缩到D:\software\php4423.将D:\software\php442增加到环境变量PATH中4. ...
- cita 源码研究
适用环境 vim + YouCompleteMe 使用 github 源,不能使用 ustc 源 git clone --depth 1 --recusive https://github.com/k ...
- 常用命令--find
语法 find path -option [ -print ] [-exec -ok command ] {} \; find . -maxdepth 1 -type f -exec mv {} /t ...