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条 ...
随机推荐
- EDA课设-交通灯-Verilog版----FPGA--004
分得到析四个状态: S1: 主干道(绿灯亮) ,支干道(亮红灯):--40S S1: 主干道 (黄灯亮) ,支干道(亮红灯):--4S S1: 主干道 (亮红灯),支干道(绿灯亮):--20S S1: ...
- 【Linux】设置开机自启
忘记转发的哪里的. 方法 1这种方法会利用 /etc/ 中的 rc.local 文件来在启动时执行脚本与命令.我们在文件中加上一行来执行脚本,这样每次启动系统时,都会执行该脚本. 不过我们首先需要为 ...
- AcWing 313. 花店橱窗 (线性DP)打卡
题目:https://www.acwing.com/problem/content/315/ 题意:有一个矩阵,你需要在每一行选择一个数,必须保证前一行的数的下标选择在下一行的左边,即下标有单调性,然 ...
- C++ win32 dll 引用外部CLR,加载托管程序集异常-Error 10 error LNK2019: unresolved external symbol _CLRCreateInstancet
异常: Error 10 error LNK2019: unresolved external symbol _CLRCreateInstance@12 referenced in function ...
- IDEA 创建 Maven web项目注意事项
需要设置 Maven ->Runner->VM options -Dmaven.multiModuleProjectDirectory=$M2_HOME 需要添加一个archetypeCa ...
- 13. Jmeter-定时器
Jmeter-定时器介绍与使用 固定定时器 Uniform Random Timer Precise Throughput Timer Constant Throughput Timer 高斯随机定时 ...
- Npm使用遇到的问题解决
0.运行项目: 1)git clone 项目 2)项目根目录执行npm install安装依赖 3)执行npm run dev启动 1.安装cnpm: npm install -g cnpm --re ...
- Java必备主流技术流程图,写得非常好!
作者:Jay_huaxiao https://juejin.im/post/5d214639e51d4550bf1ae8df 1.spring的生命周期 Spring作为当前Java最流行.最强大的轻 ...
- k8s 组件介绍-kube-controller-manager
1. Controller Manager简介 Controller Manager作为集群内部的管理控制中心,负责集群内的Node.Pod副本.服务端点(Endpoint).命名空间(Namespa ...
- redux和react-redux
redux和react-redux的关系: redux是react的状态管理工具,却不仅仅只是为了react而生的,所以在使用中会存在痛点.而react-redux是专门为了react定制,目的是为了 ...