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

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

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

三个大根堆:

\(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. CDR X6打了3折,再送魔镜插件,是真的么?

    明人不说暗话,我.要.来.个.小.资.讯. CDR X6打了3折,再送魔镜插件,是真的么?   先来说说CorelDRAW,CorelDRAW众所周知,软件的确不便宜啊,对于个人来说,相当于一个高配苹 ...

  2. 为什么使用GitHub

    GitHub的特点: 1.开源式分布版本管理系统 2.开源项目集中的代码库 3.所有略有规模的公司都在使用 GitHub的功能介绍: 1.记录多个版本 2.查看历史操作,可以进行版本吧回退和前进的控制 ...

  3. IOS - No provisioning profiles with a valid signing identity 一种解决方法

    1.删除原有“钥匙串访问”中疑是过期的的证书: 2.在Member Center中Certificate中删除疑是有问题的Certificate,重新添加新的Certificate: 3.在“钥匙串访 ...

  4. Python-基础-day5

    1.内置函数 2.文件操作 操作文件时,一般需要经历如下步骤: 打开文件 操作文件 一.打开文件 文件句柄 = file('文件路径', '模式') 注:python中打开文件有两种方式,即:open ...

  5. 洛谷 P1029 最大公约数和最小公倍数问题

    有两种做法 一种是gcd与lcm相乘后就是两个数的乘积,枚举第一个数,算出第二数,看最大公约数是不是题目给的. 第二种就lcm/gcd的答案为两个互质的数相乘.然后就枚举有多少组互质的数相乘等于lcm ...

  6. url中jsessionid的理解

    (1) 这是一个保险措施 因为Session默认是需要Cookie支持的 但有些客户浏览器是关闭Cookie的 这个时候就需要在URL中指定服务器上的session标识,也就是5F4771183629 ...

  7. 2015 Multi-University Training Contest 7 hdu 5375 Gray code

    Gray code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  8. 2015 Multi-University Training Contest 6 hdu 5361 In Touch

    In Touch Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...

  9. &lt;pre&gt;标签

     <pre>标签最主要的认识就是预格式化文本,被包围在 pre 元素中的文本一般会保留空格和换行符.而文本也会呈现为等宽字体.经经常使用于在网页中显示计算机源码. 1.格式化文本举例 &l ...

  10. 小胖说事30------iOS 强制转成横屏的方式

    一直遇到这个问题,今天最终找到了解决方法. 在我们的项目中常常遇到横竖屏切换,而又有某个特定的界面必须是特定的显示方式(横屏或竖屏).这就须要例如以下的处理了. 强制转成横屏: if ([[UIDev ...