简介

这是我自己的一点理解,可能写的不好

点分治都学过吧。。

点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树

这个树最多有log层。。。

动态点分治:记录下每个重心的上一层重心,这棵分治树就确定了

修改就暴力在分治树中向上改,反正是log的

至于为什么叫动态点分治我不知道。。。我觉得就是点分治

做题时最主要的难点不在点分治,在于维护什么和怎样维护

例题

Bzoj1095: [ZJOI2007]Hide 捉迷藏

先搞出这个分治树,然后基本和点分治无关了

以下基于分治树

每个重心开两个堆

第一个堆记录子树中所有节点到重心的距离

第二个堆记录所有子节点的第一个堆的堆顶

那么一个节点的第二个堆堆中的最大值和次大值加起来就是子树中经过这个节点的最长链

然后开一个全局的堆,记录所有第二个堆中最大值和次大值之和

堆顶就是答案

修改就分治树中暴跳重心,大力讨论一番

代码和思路来自hzwer

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(2e5 + 10); IL ll Read(){
RG ll x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} int n, nxt[_], to[_], fst[_], cnt, deep[_], size[_], frt[_], rt, mx[_], sz;
int eul[20][_], pw[20] = {1}, lg[_], id[_], tot;
bool cls[_], vis[_];
struct Heap{
priority_queue <int> A, B;
IL void Push(RG int x){ A.push(x); } IL void Del(RG int x){ B.push(x); } IL void Pop(){ while(!B.empty() && A.top() == B.top()) A.pop(), B.pop(); A.pop(); } IL int Top(){ while(!B.empty() && A.top() == B.top()) A.pop(), B.pop(); return !A.empty() ? A.top() : 0; } IL int Size(){ return A.size() - B.size(); } IL int _Top(){ if(Size() < 2) return 0; RG int x = Top(); Pop(); RG int y = Top(); Push(x); return y; }
} A, B[_], C[_]; IL void Add(RG int u, RG int v){ to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; }
/***********************************建立分治树***************************************/
IL void Getroot(RG int u, RG int ff){
size[u] = 1; mx[u] = 0;
for(RG int e = fst[u]; e != -1; e = nxt[e]){
if(to[e] == ff || vis[to[e]]) continue;
Getroot(to[e], u);
size[u] += size[to[e]];
mx[u] = max(mx[u], size[to[e]]);
}
mx[u] = max(mx[u], sz - size[u]);
if(mx[u] < mx[rt]) rt = u;
} IL void Create(RG int u, RG int ff){
frt[u] = ff; /*记录上层重心*/ vis[u] = 1;
for(RG int e = fst[u]; e != -1; e = nxt[e]){
if(vis[to[e]]) continue;
rt = 0; sz = size[to[e]];
Getroot(to[e], 0);
Create(rt, u);
}
}
/***********************************************************************************/
IL void Dfs(RG int u, RG int ff){
eul[0][++cnt] = deep[u]; id[u] = cnt;
for(RG int e = fst[u]; e != -1; e = nxt[e]){
if(to[e] == ff) continue;
deep[to[e]] = deep[u] + 1;
Dfs(to[e], u);
eul[0][++cnt] = deep[u];
}
} IL int Query(RG int x, RG int y){
x = id[x]; y = id[y]; if(x > y) swap(x, y); RG int len = y - x + 1;
return min(eul[lg[len]][x], eul[lg[len]][y - pw[lg[len]] + 1]);
} IL int MaxDis(RG int x, RG int y){ return deep[x] + deep[y] - 2 * Query(x, y); } IL void Close(RG int x, RG int y){
if(x == y){
B[x].Push(0);
if(B[x].Size() == 2) A.Push(B[x].Top());
}
if(!frt[x]) return;
RG int ff = frt[x], dis = MaxDis(ff, y), tmp = C[x].Top(); C[x].Push(dis);
if(dis > tmp){
RG int mmx = B[ff].Top() + B[ff]._Top(), sszz = B[ff].Size();
if(tmp) B[ff].Del(tmp); B[ff].Push(dis);
RG int _mmx = B[ff].Top() + B[ff]._Top();
if(_mmx > mmx){
if(sszz >= 2) A.Del(mmx);
if(B[ff].Size() >= 2) A.Push(_mmx);
}
}
Close(ff, y);
} IL void Open(RG int x, RG int y){
if(x == y){
if(B[x].Size() == 2) A.Del(B[x].Top());
B[x].Del(0);
}
if(!frt[x]) return;
RG int ff = frt[x], dis = MaxDis(ff, y), tmp = C[x].Top(); C[x].Del(dis);
if(dis == tmp){
RG int mmx = B[ff].Top() + B[ff]._Top(), sszz = B[ff].Size();
B[ff].Del(dis); if(C[x].Top()) B[ff].Push(C[x].Top());
RG int _mmx = B[ff].Top() + B[ff]._Top();
if(_mmx < mmx){
if(sszz >= 2) A.Del(mmx);
if(B[ff].Size() >= 2) A.Push(_mmx);
}
}
Open(ff, y);
} int main(RG int argc, RG char* argv[]){
Fill(fst, -1); tot = sz = n = Read(); mx[0] = 2e9;
for(RG int i = 2; i < _; ++i) lg[i] = lg[i >> 1] + 1;
for(RG int i = 1; i < 20; ++i) pw[i] = pw[i - 1] << 1;
for(RG int i = 1, u, v; i < n; i++) u = Read(), v = Read(), Add(u, v), Add(v, u);
cnt = 0; Dfs(1, 0);
for(RG int i = 1; i <= lg[cnt]; ++i)
for(RG int j = 1; j + pw[i] - 1 <= cnt; ++j)
eul[i][j] = min(eul[i - 1][j], eul[i - 1][j + pw[i - 1]]);
Getroot(1, 0); Create(rt, 0);
for(RG int i = 1; i <= n; ++i) C[i].Push(0), cls[i] = 1, Close(i, i);
for(RG int Q = Read(); Q; --Q){
RG char op; RG int x; scanf(" %c", &op);
if(op == 'G'){
if(tot <= 1) printf("%d\n", tot - 1);
else printf("%d\n", A.Top());
}
else{
x = Read();
if(cls[x]) Open(x, x), --tot, cls[x] = 0;
else Close(x, x), ++tot, cls[x] = 1;
}
}
return 0;
}

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

  1. [bzoj1095][ZJOI2007]Hide 捉迷藏 点分树,动态点分治

    [bzoj1095][ZJOI2007]Hide 捉迷藏 2015年4月20日7,8876 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiaji ...

  2. BZOJ1095: [ZJOI2007]Hide 捉迷藏【动态点分治】

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

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

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

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

    题目链接 BZOJ1095 题解 传说中的动态点分治,一直不敢碰 今日一会,感觉其实并不艰涩难懂 考虑没有修改,如果不用树形dp的话,就得点分治 对于每个重心,我们会考虑其分治的子树内所有点到它的距离 ...

  5. 2019.01.10 bzoj1095: [ZJOI2007]Hide 捉迷藏(动态点分治)

    传送门 蒟蒻真正意义上做的第一道动态点分治! 题意:给一棵最开始所有点都是黑点的树,支持把点的颜色变成从黑/白色变成白/黑色,问当前状态树上两个最远黑点的距离. 思路: 首先考虑不带修改一次点分治怎么 ...

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

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

  7. BZOJ1095: [ZJOI2007]Hide 捉迷藏【线段树维护括号序列】【思维好题】

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

  8. bzoj千题计划245:bzoj1095: [ZJOI2007]Hide 捉迷藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1095 查询最远点对,带修改 显然可以用动态点分治 对于每个点,维护两个堆 堆q1[x] 维护 点分树 ...

  9. BZOJ1095 [ZJOI2007]Hide 捉迷藏

    动态树分治,用三个set分别维护每个重心到每一个子树的距离种类.每个重心所有子树的最大值和次大值.全局答案的最大值.复杂度O(nlogn^2) 代码 #include<cstdio> #i ...

随机推荐

  1. jdk 1.8 开发环境配置

    计算机->右键->属性->高级系统设置->环境变量->系统变量 新建系统变量:JAVA_HOME,变量值为:C:\Program Files (x86)\Java\jdk ...

  2. PHP文件头BOM头问题

    前几天我们公司服务器出现了一个离奇的问题,服务器与本地文件代码完全一致,本地运行正常,到了测试环境服务器之后,各种问题一个又一个浮现,先是后台验证码不显示,以为是session写入失败,又是怀疑gd库 ...

  3. 1.9 list 列表

    列表是什么? list是Python中的基本数据结构之一,属于可变序列,所以前文中讲的可变序列的通用操作都适用于list. 这一节讲列表的特性吧. 特性一: 列表是包含任意对象的有序集合,同一个列表中 ...

  4. Qt 5.9.4 如何静态编译和部署?

    Qt 5.9.4 如何静态编译和部署? MSVC2015 x86 静态编译 Qt 部署静态库 VS2015 部署静态库 1. MSVC2015 x86 静态编译 1.1 Qt 官网下载最新源代码 立即 ...

  5. CodeForces - 796D Police Stations bfs

    思路:删除尽量多的边使得所有点都能在限制距离之内到达一个警局,删除边会形成多棵子树,最多只能k棵.其实就是以每个警局为根结点,把整棵树划分为以警局为根结点的k棵树,说明要删除的边的数量就是k-1条,即 ...

  6. cronatab周期性任务

    要执行周期性任务,要保证服务运行.服务名为crond:service crond start ; systemctl start crond; 配置文件 /etc/crontab cron的日志文件 ...

  7. linux Cacti监控服务器搭建

    搭建Cacti监控服务器 部署安装环境(lamp) [root@zhuji1 ~]# yum -y install httpd [root@zhuji1 ~]# yum -y install php ...

  8. javascript form表单常用的正则表达式

    form验证时常用的几个正则表达式 座机: \d{3,4}-\d{7,8} 手机号: /^1[34578][0-9]{9}$/ (\86)?\s+1[34578]\d{0-9} (\+86)?\s*1 ...

  9. Android热修复技术选型——三大流派解析

    声明,本文转载自微信公众号文章 2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们 ...

  10. linux 更改用户的默认shell

    由于卸载了zsh.导致用户的bash没有更新 用户无法登录.后来通过grup更改.修改/etc/passwd中的用户的shell成功 将下面的红色的更改成bash即可. root:x:::root:/ ...