点分树一点都不会啊(还是太菜了)

点分树就是我们点分治构成的新树。满足深度很小。

然后我们就可以在上面瞎维护东西了。

三个大根堆:

\(C[u]\)里装的是点分树中u的子树所有点到点分树中u的父亲的距离。

\(B[u]\)里装的是点分树中u的所有儿子的C的最大值。

\(A\)里装的是所有\(B\)的最大值与次大值之和。

\(A\)的堆顶就是答案。

(我一开始一直以为两个堆就行,对第三个对表示疑惑,又懒得深入想,一直翻题解。千万不能犯懒不想啊)

我们找答案可以快速找到。问题是怎么维护?

因为我们是点分树,深度小,可以直接一个一个跳到根暴力修改维护。具体一些就是设删的点为\(x\),跳到一个点\(u\)把\(x\)的贡献从\(C[u]\)中删掉,然后重新跟新\(B[u]\)和\(A\)。

至此本题得到解决,就是我代码常数太大。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=200100;
struct que{
priority_queue<int> x,y;
inline void push(int a){x.push(a);}
inline void del(int a){y.push(a);}
inline int top(){while(y.size()&&x.top()==y.top())x.pop(),y.pop();return x.top();}
inline int size(){return x.size()-y.size();}
inline void pop(){while(y.size()&&x.top()==y.top())x.pop(),y.pop();x.pop();}
inline int sectop(){int a=top();pop();int b=top();push(a);return b;}
}A,B[N],C[N];
int cnt,head[N];
int light[N],tot,n,m;
int root,size[N],g[N],vis[N],all,f[N];
int dep[N],mn[N*2][24],num,dfn[N];
int Log[N];
struct edge{
int to,nxt;
}e[N*2];
inline void add_edge(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
inline void dfs(int u,int f){
dfn[u]=++num;
dep[u]=dep[f]+1;
mn[num][0]=dep[u];
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs(v,u);
mn[++num][0]=dep[u];
}
}
inline void getroot(int u,int f){
g[u]=0;size[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f||vis[v])continue;
getroot(v,u);
g[u]=max(g[u],size[v]);
size[u]+=size[v];
}
g[u]=max(g[u],all-size[u]);
if(g[u]<g[root])root=u;
}
inline int getdep(int x,int y){
int a=dfn[x];
int b=dfn[y];
if(a>b)swap(a,b);
int len=Log[b-a+1];
return min(mn[a][len],mn[b-(1<<len)+1][len]);
}
inline int dis(int x,int y){
return dep[x]+dep[y]-2*getdep(x,y);
}
inline void work(int u,int ff){
C[root].push(dis(u,f[root]));
size[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==ff||vis[v])continue;
work(v,u);
size[u]+=size[v];
}
}
inline void pusha(int x){
if(B[x].size()>=2)A.push(B[x].top()+B[x].sectop());
}
inline void dela(int x){
if(B[x].size()>=2)A.del(B[x].top()+B[x].sectop());
}
inline void build(int u,int ff){
f[u]=ff;vis[u]=1;
B[u].push(0);
work(u,0);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v])continue;
root=0,all=size[v];
getroot(v,0);
v=root;
build(root,u);
B[u].push(C[v].top());
}
pusha(u);
}
inline void on(int x){
dela(x);
B[x].del(0);
pusha(x);
for(int i=x;f[i];i=f[i]){
dela(f[i]);
B[f[i]].del(C[i].top());
C[i].del(dis(x,f[i]));
if(C[i].size())B[f[i]].push(C[i].top());
pusha(f[i]);
}
}
inline void off(int x){
dela(x);
B[x].push(0);
pusha(x);
for(int i=x;f[i];i=f[i]){
dela(f[i]);
if(C[i].size())B[f[i]].del(C[i].top());
C[i].push(dis(x,f[i]));
B[f[i]].push(C[i].top());
pusha(f[i]);
}
}
void prework(){
for(int j=1;j<=Log[num];j++)
for(int i=1;i+(1<<j)-1<=num;i++)
mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
}
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int main(){
n=read();
Log[0]=-1;for(int i=1;i<=200000;i++)Log[i]=Log[i>>1]+1;
for(int i=1;i<n;i++){
int u=read(),v=read();
add_edge(u,v);add_edge(v,u);
}
dfs(1,0);
prework();
g[0]=n;root=0;all=n;
getroot(1,0);build(root,0);
tot=n;
m=read();
char s;
while(m--){
s=getchar();
if(s=='G'){
if(tot<=1)printf("%d\n",tot-1);
else printf("%d\n",A.top());
}
else{
int x=read();
if(light[x]==0)on(x),tot--;
else off(x),tot++;
light[x]^=1;
}
}
return 0;
}

[ZJOI2007]捉迷藏 (点分树+堆*3)的更多相关文章

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

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

  2. 洛谷 P2056 [ZJOI2007]捉迷藏 题解【点分治】【堆】【图论】

    动态点分治入 门 题? 题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由 \(N\) 个屋 ...

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

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

  4. 一篇自己都看不懂的点分治&点分树学习笔记

    淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...

  5. 洛谷 P2056 [ZJOI2007]捉迷藏 解题报告

    P2056 [ZJOI2007]捉迷藏 题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由\ ...

  6. 树上最长链 Farthest Nodes in a Tree LightOJ - 1094 && [ZJOI2007]捉迷藏 && 最长链

    树上最远点对(树的直径) 做法1:树形dp 最长路一定是经过树上的某一个节点的. 因此: an1[i],an2[i]分别表示一个点向下的最长链和次长链,次长链不存在就设为0:这两者很容易求 an3[i ...

  7. 树&堆

    树 什么是树? 大概像下面这样: 树的概念 树的每个点被称为节点: 连接的两个点,一个为父节点,一个为子节点,例如上图中,\(1\)是\(4\)的父节点,\(4\)是\(1\)的子节点: 没有父节点的 ...

  8. Luogu P2056 [ZJOI2007]捉迷藏

    入坑动态点分治的题目,感觉还不错被卡常后重构代码 首先静态点分治相信大家肯定都会,就是不断找重心然后暴力计算每棵子树内的贡献. 这题如果只有单次询问,我们很容易想到对于每个分治中心的所以儿子的子树中找 ...

  9. P2056 [ZJOI2007]捉迷藏

    传送门 如果没有修改显然就直接点分治 有修改那就动态点分治 动态点分治就是在点分树上维护一些东西,查询时也在点分树上查 因为点分树深度是$log$的所以可以保证时间复杂度 此题我们需要在点分树上维护 ...

随机推荐

  1. day07 分支,循环

    目录 if(分支) if的语法 if...else... if...elif...else if的嵌套 for循环 for-else 语句 for循环的嵌套(重要) range介绍 while循环 w ...

  2. java的算法实现冒泡

    package xutao3;public class test1 { public static void main(String[] args) { int[] arr={12,88,66,55, ...

  3. 【XSY2989】字符串

    题目来源:NOI2018模拟测试赛(二十六) 题解: 首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果: 一个串出现有三种情况:在前半部分,在后半部分或穿过中 ...

  4. gcp – 源于CP的高级命令行文件拷贝工具

    作者:linux 出处:http://linux.cn/thread/11868/1/1/ gcp – 源于CP的高级命令行文件拷贝工具 几周前,我们讨论了高级拷贝(修改于cp命令,让其可以显示复制进 ...

  5. oracle 用户解锁和修改用户密码

    1.安装教程参看:https://jingyan.baidu.com/article/3c48dd34be2a32e10be35881.html 2.用户解锁 --> 运行cmd --> ...

  6. java内存管理之内存模型

    1,运行时数据区域 1. 程序计数器 (program counter register) 2. Java虚拟机栈 (jvm stack) 3. 本地方法栈 (native method stack) ...

  7. sql学习笔记(18)-----------数据库创建过程

    手动创建数据库的步骤:   第一步:决定数据库实例的SID 数据库实例的SID用来将当前实例和以后可能创建的实例进行区分 % setenv ORACLE_SID mynewdb     第二步:建立数 ...

  8. poj 2612 Mine Sweeper

    Mine Sweeper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6429   Accepted: 2500 Desc ...

  9. Android This Activity already has an action bar supplied by the window decor

    This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_ ...

  10. legend---十一、thinkphp事务中if($ans1&&$ans2){}else{}方式和try{}catch{}方式事务操作的区别在哪里

    legend---十一.thinkphp事务中if($ans1&&$ans2){}else{}方式和try{}catch{}方式事务操作的区别在哪里 一.总结 一句话总结:执行的条件其 ...