传送门

解题思路

  点分树其实就是在点分治的基础上,把重心连起来。这样树高是$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 捉迷藏(动态点分治)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 1095: [ZJOI2007]Hide 捉迷藏

    Description 一棵树,支持两个操作,修改一个点的颜色,问树上最远的两个白点距离. Sol 动态点分治. 动态点分治就是将每个重心连接起来,形成一个跟线段树类似的结构,当然它不是二叉的... ...

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

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

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

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

  9. 【刷题】BZOJ 1095 [ZJOI2007]Hide 捉迷藏

    Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...

随机推荐

  1. JS基础入门篇(六)— 数据类型

    1.数据类型 数据类型:我感觉就是对数据的种类进行分类.就好比把人分为儿童,青少年,中年,老年一样. 基础数据类型: Number(数字),String(字符串),Null(空),Undefined( ...

  2. dubbo漫谈二

    转:腾信视频 阿甘 https://ke.qq.com/course/216518 https://blog.csdn.net/u013142781/article/details/50396621 ...

  3. ES6 Generator使用

    // generator介绍: function* hello() { console.log("hello world") } hello();//没有执行 // 直接调用hel ...

  4. play framework 在idea简单运行配置(mac为例)

    文章目录 play 最基本的构建 在idea中配置 配置jdk相关 配置play 运行 运行 play 最基本的构建 https://blog.csdn.net/dataiyangu/article/ ...

  5. Linux操作系统(四)_部署MySQL

    一.部署过程 1.当前服务器的内核版本和发行版本 cat /etc/issue uname -a 2.检查系统有没有自带mysql,并卸载自带版本 yum list installed | grep ...

  6. 转 linux 服务器内存占用统计

    linux 服务器内存占用统计  原文: https://www.cnblogs.com/eaglediao/p/6641811.html 当前内存占用率的计算,是根据top命令显示的Mem.used ...

  7. BZOJ 4657 (网络流)

    题面 Nick最近在玩一款很好玩的游戏,游戏规则是这样的: 有一个n*m的地图,地图上的每一个位置要么是空地,要么是炮塔,要么是一些BETA狗,Nick需要操纵炮塔攻击BETA狗们. 攻击方法是:对于 ...

  8. java面试题-看到那记录到哪

    哈希冲突 如果两个不同的元素,通过哈希函数得到的实际存储地址相同怎么办?也就是说,当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲 ...

  9. MySQLSyntaxErrorException: Row size too large 转摘自:https://confluence.atlassian.com/display/CONFKB/MySQLSyntaxErrorException%3A+Row+size+too+large

    Symptoms The following appears in the atlassian-confluence.log: Caused by: com.mysql.jdbc.exceptions ...

  10. JQ的live学习

    $("#StartTime").live("blur keypress keyup",function(){ if($("#EndTime" ...