[BZOJ1095]捉迷藏
点了动态点分治的科技树,这道题是树形态不变的动态点分治,形态变化的话...待会补
考虑点分治过程中的这样一种结构:按递归层次把当前层的重心与上层重心互相连接,这就是点分治树,容易看出它的树高只有$O(\log_2n)$
对这棵树进行讨论,先考虑没有修改怎么做,对于点分树上的一个点$x$,我们遍历它的每个儿子$u$的子树并找到$u$的子树内的所有点到$x$的最大距离,记为$far_u$,那么$x$的所有儿子$u$的$far_u$中最大和次大加起来就是经过$x$的答案
因为有修改所以我们需要把$u$子树内的所有点到$x$的距离用一个堆存在节点$u$(不妨称此堆为堆$1$),同时我们需要把$x$的所有儿子$u$的堆$1$堆顶用一个堆存在$x$(不妨称为堆$2$),再用堆$3$存所有(堆$2$的最大值和次大值之和),此时堆$3$的堆顶就是答案
到这里,修改就变得很简单了,改堆$1$的同时更新堆$2$堆$3$即可
实现的时候如果某个节点是可用的,它的堆$2$内要有一个$0$表示路径从$x$出发,修改时也要记得加$0$或删$0$
#include<stdio.h>
#include<queue>
using namespace std;
const int inf=2147483647;
struct heap{
priority_queue<int>h,d;
void push(int v){h.push(v);}
void erase(int v){d.push(v);}
void adj(){
while(!d.empty()&&h.top()==d.top()){
h.pop();
d.pop();
}
}
int top(){
adj();
return h.top();
}
void pop(){
adj();
h.pop();
}
int sec(){
int x,y;
x=top();
pop();
y=top();
push(x);
return y;
}
int size(){return h.size()-d.size();}
}h1[100010],h2[100010],al;
int h[100010],to[200010],nex[200010],M;
void add(int a,int b){
M++;
to[M]=b;
nex[M]=h[a];
h[a]=M;
}
int fa_[100010][17],dep[100010];
void dfs(int x){
for(int i=h[x];i;i=nex[i]){
if(to[i]!=fa_[x][0]){
fa_[to[i]][0]=x;
dep[to[i]]=dep[x]+1;
dfs(to[i]);
}
}
}
int lca(int x,int y){
int i;
if(dep[x]<dep[y])swap(x,y);
for(i=16;i>=0;i--){
if(dep[fa_[x][i]]>=dep[y])x=fa_[x][i];
}
if(x==y)return x;
for(i=16;i>=0;i--){
if(fa_[x][i]!=fa_[y][i]){
x=fa_[x][i];
y=fa_[y][i];
}
}
return fa_[x][0];
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
int siz[100010],n;
bool v[100010];
void dfs1(int fa,int x){
n++;
siz[x]=1;
for(int i=h[x];i;i=nex[i]){
if(!v[to[i]]&&to[i]!=fa){
dfs1(x,to[i]);
siz[x]+=siz[to[i]];
}
}
}
int mn,cn;
void dfs2(int fa,int x){
int i,k;
k=0;
for(i=h[x];i;i=nex[i]){
if(!v[to[i]]&&to[i]!=fa){
dfs2(x,to[i]);
k=max(k,siz[to[i]]);
}
}
k=max(k,n-siz[x]);
if(k<mn){
mn=k;
cn=x;
}
}
void dfs3(heap&p,int s,int fa,int x){
p.push(dis(x,s));
for(int i=h[x];i;i=nex[i]){
if(!v[to[i]]&&to[i]!=fa)dfs3(p,s,x,to[i]);
}
}
int fa[100010];
int solve(int f,int x){
n=0;
dfs1(0,x);
mn=inf;
dfs2(0,x);
x=cn;
if(f)dfs3(h1[x],f,0,x);
fa[x]=f;
v[x]=1;
h2[x].push(0);
for(int i=h[x];i;i=nex[i]){
if(!v[to[i]])h2[x].push(h1[solve(x,to[i])].top());
}
if(h2[x].size()>1)al.push(h2[x].top()+h2[x].sec());
return x;
}
void modify(int x,int v,bool f){
if(h2[fa[x]].size()>1)al.erase(h2[fa[x]].top()+h2[fa[x]].sec());
if(h2[fa[x]].size()>0&&h1[x].size()>0)h2[fa[x]].erase(h1[x].top());
f?h1[x].push(v):h1[x].erase(v);
if(h1[x].size()>0)h2[fa[x]].push(h1[x].top());
if(h2[fa[x]].size()>1)al.push(h2[fa[x]].top()+h2[fa[x]].sec());
}
void change(int x){
v[x]^=1;
if(h2[x].size()>1)al.erase(h2[x].top()+h2[x].sec());
v[x]?h2[x].push(0):h2[x].erase(0);
if(h2[x].size()>1)al.push(h2[x].top()+h2[x].sec());
for(int i=x;fa[i];i=fa[i])modify(i,dis(fa[i],x),v[x]);
}
int main(){
int n,m,i,j,x,y,sum;
char s[5];
scanf("%d",&n);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dep[1]=1;
dfs(1);
for(j=1;j<17;j++){
for(i=1;i<=n;i++)fa_[i][j]=fa_[fa_[i][j-1]][j-1];
}
solve(0,1);
scanf("%d",&m);
sum=n;
while(m--){
scanf("%s",s);
if(s[0]=='G')
printf("%d\n",sum<2?sum-1:al.top());
else{
scanf("%d",&x);
v[x]?(sum--):(sum++);
change(x);
}
}
}
[BZOJ1095]捉迷藏的更多相关文章
- 【BZOJ1095】捉迷藏(动态点分治)
[BZOJ1095]捉迷藏(动态点分治) 题面 BZOJ 题解 动态点分治板子题 假设,不考虑动态点分治 我们来想怎么打暴力: \(O(n)DP\)求树的最长链 一定都会.不想解释了 所以,利用上面的 ...
- 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏
简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆
[BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...
- [bzoj1095][ZJOI2007]Hide 捉迷藏 点分树,动态点分治
[bzoj1095][ZJOI2007]Hide 捉迷藏 2015年4月20日7,8876 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiaji ...
- 【BZOJ1095】 Hide 捉迷藏
Time Limit: 4000 ms Memory Limit: 256 MB Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.W ...
- BZOJ1095:[ZJOI2007]Hide 捉迷藏(动态点分治)
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...
- BZOJ1095: [ZJOI2007]Hide 捉迷藏【线段树维护括号序列】【思维好题】
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- 「BZOJ1095」[ZJOI2007] Hide 捉迷藏
题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条 ...
随机推荐
- 【BZOJ 4034】[HAOI2015]树上操作 差分+dfs序+树状数组
我们只要看出来这道题 数组表示的含义就是 某个点到根节点路径权值和就行 那么我们可以把最终答案 看做 k*x+b x就是其深度 ,我们发现dfs序之后,修改一个点是差分一个区间,修改一个点的子树,可以 ...
- git使用笔记(六)github
By francis_hao Nov 20,2016 github介绍 github是一个网站https://github.com/,可以实现基于git(当然,svn也是可以的)的代码托管工作. ...
- java的GC与内存泄漏
从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...
- bzoj4589 FWT xor版本
4589: Hard Nim Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 865 Solved: 484[Submit][Status][Disc ...
- python实现后台系统的JWT认证
介绍一种适用于restful+json的API认证方法,这个方法是基于jwt,并且加入了一些从oauth2.0借鉴的改良. 1. 常见的几种实现认证的方法 首先要明白,认证和鉴权是不同的.认证是判定用 ...
- 布局之BFC
BFC 什么是BFC,在哪里需要用到BFC,BFC有什么规则?生成BFC有什么条件?这几个问题,我将为大家一一解释,下面我们进入正题. BFC(Block formatting context)直译为 ...
- 【BZOJ】[SDOI2009]HH的项链
[算法]主席树||离线+树状数组 [题解] 主席树经典应用:找区间不同的数字个数. 做法:记录每个数上一次出现的位置last[i],对last建权值线段树,对于区间询问last[i]<L的数字个 ...
- 【洛谷 P3834】 可持久化线段树1(主席树)
题目链接 主席树=可持久化权值线段树. 如果你不会可持久化线段树,请右转 如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现. 可持久化线段树是支持查询历史版本的. 我们对每个数都进 ...
- [bzoj2631]tree——lct
Brief Description 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: u v c:将u到v的路径上的点的权值都加上自然数c: u1 v1 u2 ...
- 2.jinja2
1.jinja2模板介绍和查找路径 from flask import Flask, render_template import os # 之前提到过在渲染模板的时候,默认会从项目根目录下的temp ...