原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html

题目传送门 - BZOJ1095

题意

  有 N 个点,每一个点是黑色或者白色,一开始所有点的颜色都是黑色。有 M 次操作,每次操作有两种类型:1. 修改一个点的颜色;2. 查询树上所有黑色点对之间的距离最大值。

  $N\leq 100000,m\leq 500000$

题解

  写个动态点分治。

  对于一个点分中心,维护两个可删堆:

  1. 维护一下当前连通块的所有黑点到 当前点分中心在点分树上的父亲节点 之间的距离。

  2. 维护一下当前点分中心所有子树的最深深度,这个东西显然可以通过子树中维护的 1. 来得到。

  对于全局,维护一个可删堆,把每一个节点的 2 号堆中最大两个值的和扔进去。

  这个可删堆有一种方便的写法,见代码。

  每次修改直接暴力上跳。注意堆中元素个数不足的情况。

  求 LCA 最好写欧拉序 + 倍增。不然,虽然能在 BZOJ 通过,但是会在一个测试点 5s 的情况下被卡常。

代码

#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
struct AB_Heap{
priority_queue <int> A,B;
int sz;
void clear(){
while (!A.empty())
A.pop();
while (!B.empty())
B.pop();
sz=0;
}
int size(){return sz;}
void push(int x){A.push(x),sz++;}
void pop(int x){B.push(x),sz--;}
int top(){
while (!B.empty()&&A.top()==B.top())
A.pop(),B.pop();
return A.top();
}
int top2(){
int x=top(),y;
pop(x),y=top(),push(x);
return x+y;
}
}S[N],SF[N],ans;
int n,m,tot;
int depth[N],in[N],out[N],eu[N*2],ST[N*2][20],Log[N*2];
int Dfa[N],vis[N],Time=0,size[N],Max[N],now[N];
vector <int> e[N];
void dfs1(int x,int pre,int d){
depth[x]=d,eu[in[x]=++Time]=x;
for (vector <int> :: iterator y=e[x].begin();y!=e[x].end();y++)
if ((*y)!=pre)
dfs1(*y,x,d+1),eu[++Time]=x;
out[x]=Time;
}
void Get_ST(int n){
Log[1]=0;
for (int i=2;i<=n;i++)
Log[i]=Log[i>>1]+1;
for (int i=1;i<=n;i++){
ST[i][0]=eu[i];
for (int j=1;j<20;j++){
ST[i][j]=ST[i][j-1];
int p=i-(1<<(j-1));
if (p>0&&depth[ST[p][j-1]]<depth[ST[i][j]])
ST[i][j]=ST[p][j-1];
}
}
}
int LCA(int x,int y){
if (in[x]>out[y])
swap(x,y);
int L=in[x],R=out[y],d=Log[R-L+1];
int a=ST[L+(1<<d)-1][d],b=ST[R][d];
return depth[a]<depth[b]?a:b;
}
int Distance(int x,int y){
return depth[x]+depth[y]-2*depth[LCA(x,y)];
}
int Node[N],Node_cnt=0;
void dfs2(int x,int pre){
if (vis[x]>=Time){
size[x]=0;
return;
}
size[x]=1,vis[x]=Time,Max[x]=0;
Node[++Node_cnt]=x;
for (vector <int> :: iterator y=e[x].begin();y!=e[x].end();y++){
if ((*y)==pre)
continue;
dfs2(*y,x);
size[x]+=size[*y];
Max[x]=max(Max[x],size[*y]);
}
}
int build(int x,int pre){
Time++,Node_cnt=0,dfs2(x,0);
int mi=x,v=Max[x];
for (int i=1;i<=Node_cnt;i++){
int y=Node[i],vy=max(Max[y],size[x]-size[y]);
if (vy<v)
v=vy,mi=y;
}
Dfa[x=mi]=pre,vis[x]=1e9,SF[x].clear();
for (int i=1;i<=Node_cnt;i++)
SF[x].push(Distance(pre,Node[i]));
S[x].clear(),S[x].push(0);
for (vector <int> :: iterator y=e[x].begin();y!=e[x].end();y++)
if (vis[*y]<1e9)
S[x].push(SF[build(*y,x)].top());
if (S[x].size()>=2)
ans.push(S[x].top2());
return x;
}
void update(int x){
if (S[x].size()>=2) ans.pop(S[x].top2());
if (now[x])
S[x].push(0);
else
S[x].pop(0);
if (S[x].size()>=2) ans.push(S[x].top2());
for (int y=x;Dfa[y];y=Dfa[y]){
int z=Dfa[y],d=Distance(x,z);
if (SF[y].size()&&SF[y].top()>d)
if (now[x])
SF[y].push(d);
else
SF[y].pop(d);
else {
if (S[z].size()>=2) ans.pop(S[z].top2());
if (SF[y].size()) S[z].pop(SF[y].top());
if (now[x])
SF[y].push(d);
else
SF[y].pop(d);
if (SF[y].size()) S[z].push(SF[y].top());
if (S[z].size()>=2) ans.push(S[z].top2());
}
}
tot+=now[x]?1:-1,now[x]^=1;
}
int main(){
tot=n=read();
for (int i=1;i<n;i++){
int a=read(),b=read();
e[a].push_back(b);
e[b].push_back(a);
}
dfs1(1,0,0),Get_ST(n*2-1);
ans.clear(),build(1,0);
m=read();
while (m--){
char ch[10];
scanf("%s",ch);
if (ch[0]=='C')
update(read());
else
printf("%d\n",tot<=1?tot-1:ans.top());
}
return 0;
}

  

BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆的更多相关文章

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

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

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

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

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

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

  4. BZOJ1095:[ZJOI2007]Hide 捉迷藏(动态点分治)

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

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

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

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

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

  7. bzoj 1095 Hide 捉迷藏 - 动态点分治 -堆

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

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

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

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

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

随机推荐

  1. mysql5.7 pxc

    pxc优点总结:可以达到时时同步,无延迟现象发生完全兼容MySQL对于集群中新节点的加入,维护起来很简单数据的强一致性不足之处总结:只支持Innodb存储引擎存在多节点update更新问题,也就是写放 ...

  2. tcp和udp协议的聊天 和udp协议的时间同步机制-----编码

    tcp协议聊天 服务端:: 客户端 udp协议的聊天 ############ udp协议 ########### 服务器 import socket sk = socket.socket(type ...

  3. 前端-----margin用法(盒子模型里补充)

    margin塌陷问题 当时说到了盒模型,盒模型包含着margin,为什么要在这里说margin呢?因为元素和元素在垂直方向上margin里面有坑. 我们来看一个例子: html结构: <div ...

  4. 借助dubbo-admin来管理你的服务

      1.  Github上下载最新的dubbo源码包并解压   2. 修改配置信息(打开 dubbo-admin/src/main/webapp/WEB-INF下的dubbo.properties,修 ...

  5. java操作redis之按照关键字删除缓存数据

    思路: 1.链接redis数据库,连接成功2.js.del(key),按照指定的key进行删除,封装删除方法3.js.keys("*"),获取所有键keys的集合,对set集合进行 ...

  6. JsonResponse

    1.JsonResponse class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None ...

  7. 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]

    传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...

  8. css中input框不可点击+首行缩进

    Css 1)text-indent::首行缩进 2)disabled="true"设置input框不可以点击 3)Css:xx!important:声明提前优先级最高..!impo ...

  9. 修改 sql 提示符信息:

    Last login: Thu Dec 8 19:18:08 2016 from 192.168.242.1 [root@localhost ~]# su - oracle [oracle@local ...

  10. Confluence 6 删除垃圾内容

    属性(profile)垃圾 属性垃圾的定义为,一个垃圾用户在 Confluence 创建了用户,但是这个用户在自己的属性页面中添加了垃圾 URL. 如果你有很多垃圾用户在你的系统中创建了属性,你可以使 ...