终于把这个坑填了..

按重心分治建树,每个点存两个堆,第一个存的是这个点子树中的点到父重心的距离,第二个存的是子节点第一个堆的堆顶,同时有一个全局答案堆,存的是每个点第二个堆的最大值+次大值。

20亿个蒟蒻们给了我一份漏洞百出的代码,害的我想了半天..

#include <cstdio>
#include <queue>
using namespace std; const int N=,M=;
char op[];
int n,e,x,y,q,tt,sm,mn,rt,hd[N],nx[M],to[M],v[N],f[N],a[N],d[N],sz[N],g[N][];
struct hep {
priority_queue<int> ad,dl;
void pu(int x) {ad.push(x);}
void po(int x) {dl.push(x);}
int tp() {while(!dl.empty()&&ad.top()==dl.top()) ad.pop(),dl.pop(); return ad.top();}
int gt() {int a=tp(); ad.pop(); int b=tp(); ad.push(a); return a+b;}
}a1,q1[N],q2[N];
void ad(int x,int y) {to[++e]=y,nx[e]=hd[x],hd[x]=e;} void dfs2(int x) {for(int i=hd[x];i;i=nx[i]) if(!d[to[i]]) d[to[i]]=d[x]+,g[to[i]][]=x,dfs2(to[i]);}
int lca(int x,int y) {
if(d[x]<d[y]) swap(x,y);
for(int i=;~i;i--) if(d[g[x][i]]>=d[y]) x=g[x][i];
if(x==y) return x;
for(int i=;~i;i--) if(g[x][i]^g[y][i]) x=g[x][i],y=g[y][i];
return g[x][];
}
int ds(int x,int y) {return d[x]+d[y]-d[lca(x,y)]*;}
void dfs(int x,int fa) {
sz[x]=;
for(int i=hd[x];i;i=nx[i]) if(to[i]!=fa&&!v[to[i]]) dfs(to[i],x),sz[x]+=sz[to[i]];
}
void gt(int x,int fa) {
int mx=; sz[x]=;
for(int i=hd[x];i;i=nx[i]) if(to[i]!=fa&&!v[to[i]]) gt(to[i],x),sz[x]+=sz[to[i]],mx=max(mx,sz[to[i]]);
mx=max(mx,tt-sz[x]);
if(mx<mn) mn=mx,rt=x;
}
void bd(int x,int y) {
gt(x,),f[rt]=y,v[rt]=,dfs(rt,); int k=rt;
for(int i=hd[rt];i;i=nx[i]) if(!v[to[i]]) tt=mn=sz[to[i]],bd(to[i],k);
}
void cal(int x) {
int u=x;
if(q2[x].ad.size()-q2[x].dl.size()>=) a1.po(q2[x].gt());
q2[x].pu();
if(q2[x].ad.size()-q2[x].dl.size()>=) a1.pu(q2[x].gt());
while(f[u]) {
if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=) a1.po(q2[f[u]].gt());
if(q1[u].ad.size()-q1[u].dl.size()) q2[f[u]].po(q1[u].tp());
q1[u].pu(ds(f[u],x)),q2[f[u]].pu(q1[u].tp());
if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=) a1.pu(q2[f[u]].gt());
u=f[u];
}
}
void cal2(int x) {
int u=x;
if(q2[x].ad.size()-q2[x].dl.size()>=) a1.po(q2[x].gt());
q2[x].po();
if(q2[x].ad.size()-q2[x].dl.size()>=) a1.pu(q2[x].gt());
while(f[u]) {
if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=) a1.po(q2[f[u]].gt());
q2[f[u]].po(q1[u].tp()),q1[u].po(ds(f[u],x));
if(q1[u].ad.size()-q1[u].dl.size()) q2[f[u]].pu(q1[u].tp());
if(q2[f[u]].ad.size()-q2[f[u]].dl.size()>=) a1.pu(q2[f[u]].gt());
u=f[u];
}
} int main() {
scanf("%d",&n),sm=n;
for(int i=;i<n;i++) scanf("%d%d",&x,&y),ad(x,y),ad(y,x);
tt=mn=n,bd(,),d[]=,dfs2();
for(int j=;j<;j++)
for(int i=;i<=n;i++)
g[i][j]=g[g[i][j-]][j-];
for(int i=;i<=n;i++) cal(i);
scanf("%d",&q);
while(q--) {
scanf("%s",op);
if(op[]=='G') {
if(sm<=) printf("%d\n",sm-);
else printf("%d\n",a1.tp());
}
else {
scanf("%d",&x),a[x]^=;
if(a[x]) sm--,cal2(x); else sm++,cal(x);
}
}
return ;
}

BZOJ1095(动态点分治+堆)的更多相关文章

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

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

  2. BZOJ_1095_[ZJOI2007]Hide 捉迷藏_动态点分治+堆

    BZOJ_1095_[ZJOI2007]Hide 捉迷藏_动态点分治+堆 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子 ...

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

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

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

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

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

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

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

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

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

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

  8. 【BZOJ1095】捉迷藏(动态点分治)

    [BZOJ1095]捉迷藏(动态点分治) 题面 BZOJ 题解 动态点分治板子题 假设,不考虑动态点分治 我们来想怎么打暴力: \(O(n)DP\)求树的最长链 一定都会.不想解释了 所以,利用上面的 ...

  9. 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏

    简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...

随机推荐

  1. jwt验证登录信息

    为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...

  2. LeetCode题型分类及索引

    目录 这是一个对LeetCode题目归类的索引,分类标准参考了July大神的<编程之法>以及LeetCode的tag项.分类可能还不太合理,逐步完善,请见谅~ 题主本人也在一点一点的刷题, ...

  3. vmware 12 安装 mac os 10.12正式版

    1.首先下载安装vmware 12 pro ,将VT打开(虚拟功能,以前安装过虚拟机点的同学可忽略). 2.下载mac ox 10.12正式版镜像文件(cdr后缀). 3.下载Unlocker208( ...

  4. j2ee基础(1)servlet的生命周期

    Servlet的生命周期 Servlet 生命周期规定了 Servlet 如何被加载.实例化.初始化. 处理客户端请求,以及何时结束服务. 该生命周期可以通过 javax.servlet.Servle ...

  5. vmvare入门(1)使用移动,不要使用复制

    1.复制虚拟机会产生新的自动网卡,原来的 System Eth0废了? 2.xftp链接的时候,要选择sftp方式连接,utf8编码.

  6. php程序报错:PHP Core Warning/cannot open shared object file: No such file or directory

    今天开发调试程序的时候报错了,现象是有时候刷新会出现如下图: 这种主要是找不到共享库文件,即.so文件,网上主要有3种解决方法: 1. 用ln将需要的so文件链接到/usr/lib或者/lib这两个默 ...

  7. Qt自定义控件

    Qt创建自定义控件教程 一.新建Qt设计师控件 二.设置项目名称 三.选择kits 这里取消Debug选项,不需要这个选项都是编译为dll文件直接调用. 删除掉MyControl原有的.h和cpp文件 ...

  8. Django:(博客系统)使用使用mysql数据->后台管理tag/post/category的配置

    Django后台一般是不需要人为的去开发的,因为django已经通过配置实现哪些模块是后台需要管理,如何排序,列表展示哪些列,列显示名称,是否为空(默认值),过滤条件,分页页数,列表中哪些项可编辑等等 ...

  9. Html5 监听拦截Android返回键方法详解

    浏览器窗口有一个history对象,用来保存浏览历史. 如果当前窗口先后访问了三个网址,那么history对象就包括三项,history.length属性等于3. history对象提供了一系列方法, ...

  10. Flask博客开发——登录验证码

    这部分为Flask博客的登录页面加个验证码.使用了PIL模块生成验证码图片,并通过Flask的session机制,进行验证码验证. 1.生成验证码 使用string模块:string.ascii_le ...