题目链接

BZOJ1095

题解

传说中的动态点分治,一直不敢碰
今日一会,感觉其实并不艰涩难懂

考虑没有修改,如果不用树形dp的话,就得点分治
对于每个重心,我们会考虑其分治的子树内所有点到它的距离,然后取所有不同子树中最大的两个相加来更新答案

如果带修改怎么办呢?
考虑一个点\(u\)被修改了,会对哪些点产生影响。显然是包含它的分治子树之中

点分树

我们在点分治过程中,将每个重心与上一层分治重心相连,形成一棵树结构,叫做点分树
一个点被修改,仅影响其在点分树中所有祖先的答案

那么这样我们就可以维护了
对于每个点\(u\),我们开两个堆分别储存一下信息:
堆\(C\):以\(C\)为根的分治子树中所有点到点分树中\(u\)的父亲的距离
堆\(B\):\(u\)在点分树中所有儿子\(C\)堆堆顶

对于全局开一个堆\(A\),储存所有堆\(B\)的最大值和次大值之和

那么堆\(A\)堆顶就是当前的答案

对于堆来说,插入是很方便的,但是删除就没那么简单,我们可以对每个堆再开一个堆,储存所有被删除的值,每次访问堆顶时,如果删除堆堆顶与当前堆顶相同,那么都\(pop\)掉,直到不相同位置

还要注意的就是堆间操作的顺序
我们要操作\(C\),就得先将父亲\(B\)堆中该\(C\)堆堆顶\(pop\)掉,操作完再加回去
同样,我们要操作\(B\),也得先从\(A\)中将对应贡献删除

感觉这题难点并不在动态点分治。。。而是在堆的维护吧。。。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 100005,maxm = 200005,INF = 1000000000;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
struct heap{priority_queue<int> a,b;void ins(int x){if (x >= 0) a.push(x);}void del(int x){if (x >= 0) b.push(x);}int size(){return a.size() - b.size();}int top(){if (!size()) return -1;while (!b.empty() && a.top() == b.top()) a.pop(),b.pop();return a.top();}int sum(){if (size() < 2) return -1;int x = top(); a.pop();int y = top(); ins(x);return x + y;}
}C[maxn],B[maxn],A;
int bin[50],Log[maxm],mn[maxm][19];
int n,fa[maxn],dep[maxn],dfn[maxn],cnt;
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 1];
void build(int u,int v){ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
void dfs(int u){mn[++cnt][0] = dep[u]; dfn[u] = cnt;Redge(u) if ((to = ed[k].to) != fa[u]){fa[to] = u; dep[to] = dep[u] + 1;dfs(to);mn[++cnt][0] = dep[u];}
}
int dis(int u,int v){int l = dfn[u],r = dfn[v];if (l > r) swap(l,r);int t = Log[r - l + 1];int d = min(mn[l][t],mn[r - bin[t] + 1][t]);return dep[u] + dep[v] - (d << 1);
}
int F[maxn],Siz[maxn],vis[maxn],Fa[maxn],sum,rt;
int pre[maxn];
void getrt(int u){F[u] = 0; Siz[u] = 1;Redge(u) if (!vis[to = ed[k].to] && to != Fa[u]){Fa[to] = u; getrt(to);Siz[u] += Siz[to];F[u] = max(F[u],Siz[to]);}F[u] = max(F[u],sum - Siz[u]);if (F[u] < F[rt]) rt = u;
}
int c[maxn],ci;
void dfs1(int u){Siz[u] = 1; c[++ci] = u;Redge(u) if (!vis[to = ed[k].to] && to != Fa[u]){Fa[to] = u; dfs1(to);Siz[u] += Siz[to];}
}
void solve(int u){vis[u] = true; Siz[u] = 1; ci = 0;Redge(u) if (!vis[to = ed[k].to]){Fa[to] = u; dfs1(to);Siz[u] += Siz[to];}if (pre[u]){C[u].ins(dis(u,pre[u]));REP(i,ci) C[u].ins(dis(c[i],pre[u]));}Redge(u) if (!vis[to = ed[k].to]){F[rt = 0] = INF; sum = Siz[to];getrt(to);pre[rt] = u; to = rt;solve(rt);B[u].ins(C[to].top());}B[u].ins(0);A.ins(B[u].sum());
}
int light[maxn];
void Insert(int x){int v;A.del(B[x].sum());B[x].ins(0);A.ins(B[x].sum());for (int u = x; pre[u]; u = pre[u]){v = pre[u];A.del(B[v].sum());B[v].del(C[u].top());C[u].ins(dis(x,v));B[v].ins(C[u].top());A.ins(B[v].sum());}
}
void Delete(int x){int v;A.del(B[x].sum());B[x].del(0);A.ins(B[x].sum());for (int u = x; pre[u]; u = pre[u]){v = pre[u];A.del(B[v].sum());B[v].del(C[u].top());C[u].del(dis(x,v));B[v].ins(C[u].top());A.ins(B[v].sum());}
}
int main(){bin[0] = 1; for (int i = 1; i <= 25; i++) bin[i] = bin[i - 1] << 1;Log[0] = -1; for (int i = 1; i < maxm; i++) Log[i] = Log[i >> 1] + 1;n = read();for (int i = 1; i < n; i++)build(read(),read());dfs(1);for (int j = 1; j <= 18; j++)for (int i = 1; i <= cnt; i++){if (i + bin[j] - 1 > cnt) break;mn[i][j] = min(mn[i][j - 1],mn[i + bin[j - 1]][j - 1]);}F[rt = 0] = INF; sum = n;getrt(1);solve(rt);int m = read(),v; char opt;while (m--){opt = getchar();while (opt != 'G' && opt != 'C') opt = getchar();if (opt == 'G'){v = A.top();printf("%d\n",v >= 0 ? v : -1);}else {v = read();light[v] ^= 1;if (!light[v]) Insert(v);else Delete(v);}}return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/9056715.html

BZOJ1095 [ZJOI2007]Hide 捉迷藏 【动态点分治 + 堆】相关推荐

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

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

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

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

  3. BZOJ1095 ZJOI2007 Hide 捉迷藏

    BZOJ1095 ZJOI2007 Hide 捉迷藏 动态树分治+堆 动态点分治 posted on 2016-06-25 11:35  wjyi 阅读( ...) 评论( ...) 编辑 收藏 转载 ...

  4. bzoj1095: [ZJOI2007]Hide 捉迷藏

    题目链接 bzoj1095 题意 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且 ...

  5. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

  6. bzoj1095 [ZJOI2007]Hide 捉迷藏

    据说是道很厉害的题....黄学长的安利啊.... 然而我却用它学分治.... 一个坑就摆在这里了.... 转载于:https://www.cnblogs.com/LLppdd/p/9124394.ht ...

  7. 【BZOJ 1095】 1095: [ZJOI2007]Hide 捉迷藏 (括号序列+线段树)

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

  8. [ZJOI2007]Hide 捉迷藏

    [ZJOI2007]Hide 捉迷藏 小岛的博客 黄学长的博客 NOI08 冬令营论文 <数据结构的提炼与压缩> 这个问题竟然还能用线段树做,拿小本本记下来. 转载于:https://ww ...

  9. BZOJ1095 [ZJOI2007]捉迷藏 动态点分治

    每次修改一个点的黑白状态,询问树上最远黑点距离 拿这个题做动态点分治模板题:(%%%PoPoQQQ大爷) 点分治的过程是对树块找重心之后分成多个小树块,降低规模分别处理的过程,把链的信息收到其中&qu ...

最新文章

  1. 【Qt】Qt程序编译成功,执行时报错:程序异常结束,crashed
  2. Java报表工具FineReport导出EXCEL的四种API
  3. R使用lm构建单变量线性回归模型
  4. 如何使用MatPlotLib绘制出具有两个 Y 轴的曲线图?
  5. CODEVS-1082-线段树练习3-splay
  6. 史上最全推荐系统传统算法合集
  7. GDI+ 设置文本对齐方式
  8. 使用java开发简单的mis系统所需的技术
  9. Sentinel降级简介_分布式系统集群限流_线程数隔离_削峰填谷_流量控制_速率控制_服务熔断_服务降级---微服务升级_SpringCloud Alibaba工作笔记0038
  10. tar ,cpio打包解压. shell脚本for,while,until循环. rpm包管理,select循环菜单,函数function,yum...
  11. 正反向数据库及生成设计报告
  12. 可能是最全的一份 2017 年中国移动互联网年度报告(建议收藏)
  13. 用Portainer或UI for Docker可视化管理树莓派容器
  14. html5仿微博代码仿新浪微博,CSS3网页制作实例:模仿新浪微博首页变化_css
  15. Matlab逆向归纳法,6.完全信息动态博弈—逆向归纳法和子博弈完美均衡.ppt
  16. 实习,内推,校招,社招的区别和联系
  17. 树莓派存储方案_树莓派搭建seafile存储重要文件
  18. LARS算法探究LOL比赛各数据对胜负的影响
  19. 2021年东莞高新企业补贴政策
  20. 图的应用:最小生成树与最短路径

热门文章

  1. Java中的单例模式
  2. 究竟应该怎么调用WCF服务?
  3. VIA笔试收集与解答
  4. 上接[翻译]ASP.NET 2.0中的健康监测系统(Health Monitoring)(1) - 基本应用
  5. 使用Docker搭建Elasticsearch集群环境
  6. React Native学习(七)—— FlatList实现横向滑动列表效果
  7. 当谈论设备指纹时,我们到底在说什么?(转)
  8. 数据加密之MD5加密
  9. 【编程之美】2.12快速寻找满足条件的两个数
  10. 生成有关 SQL Server 2005 Analysis Services 多维数据集数据源的本地化报表