Qtree4——动态点分治
题目描述
给出一棵边带权的节点数量为n的树,初始树上所有节点都是白色。有两种操作:
C x,改变节点x的颜色,即白变黑,黑变白
A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0)。
N (N <= 100000) Q <= 200000
时限1s
题解
如果没有修改的话,直接点分治,记录子树最深的白点即可。
但是有修改。
发现,点分治的递归层数是O(logn)的
而且这个递归的联通块的根形成一个树形结构。不妨叫点分树。
我们的答案是在所有递归出来的块里ans取max
发现,每次改变一个点的颜色,会影响自己的联通块,以及点分树上这个点的所有father的答案。
树高logn
所以,我们考虑暴力修改每一层的答案。
用三个堆来维护。
一个堆h0,维护这个点P所代表的点分树的联通块中所有点到点分树上P的father的距离(树上实际距离)。
(好处是,修改的时候,直接自底向上,父亲只要一个,这样不需要在上层再考虑哪个子树变了)
另一个堆h1,维护这个点P的所有儿子的堆顶的值。
我们从一个点P的h1堆里面,找到最大的和次大的,做和就是这一层的最大答案。
如果P是白点,那么答案可以只要最大的。而且ans最少是0
第三个堆,维护所有点代表的联通块的ans。最终答案就在这里。
然后,所有的修改,都是删除之后再插入。
堆的删除,用懒惰堆即可。
代码:
(实现细节较多:例如堆的empty判断)
(堆中不用记录答案出自哪里,随便删除一个,剩下那个就是没有删除的。是没有区别的。直接int的堆即可)
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
il void prin(int x){
if(x/) prin(x/);
putchar(x%+'');
}
namespace Miracle{
const int N=+;
const int inf=0x3f3f3f3f;
int n,m;
struct node{
int nxt,to;
int val;
}e[*N];
int hd[N],cnt;
il void add(int x,int y,int z){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
e[cnt].val=z;
hd[x]=cnt;
}
int fa[N];
int sz[N];
int c[N];
priority_queue<int>h[][N],d[][N],hh,dd; int dis[N][];
int dep[N];
int nowsz;
int rt,mxsz[N];
int ans[N];
bool vis[N];
int gen;
il void dfs1(int x,int ff,int d){
dep[x]=d;
sz[x]=;
mxsz[x]=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==ff) continue;
if(vis[y]) continue;
dfs1(y,x,d);
sz[x]+=sz[y];
mxsz[x]=max(mxsz[x],sz[y]);
}
mxsz[x]=max(mxsz[x],nowsz-sz[x]);
if(mxsz[x]<=nowsz/){
rt=x;
}
}
il void dfs2(int x,int ff,int d){
sz[x]=;
if(d!=) h[][rt].push(dis[x][d-]);
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(vis[y]) continue;
if(y==ff) continue;
dis[y][d]=dis[x][d]+e[i].val;
dfs2(y,x,d);
sz[x]+=sz[y];
}
}
il void clear(int x,int k){
if(h[k][x].empty()) return;
while(d[k][x].size()&&h[k][x].size()&&h[k][x].top()==d[k][x].top()){
h[k][x].pop();d[k][x].pop();
}
}
il void upda(int x){
//cout<<" updaing "<<x<<endl;
ans[x]=-inf;
if(c[x]==) ans[x]=max(ans[x],);
clear(x,);
if(!h[][x].empty()){
//cout<<" sz "<<h[1][x].size()<<" "<<d[1][x].size()<<endl;
int tmp=h[][x].top();h[][x].pop();
//cout<<" tmp "<<tmp.id<<" "<<tmp.val<<endl;
if(c[x]==){
ans[x]=max(ans[x],tmp);
}
clear(x,);
if(!h[][x].empty()){
ans[x]=max(ans[x],tmp+(h[][x].top()));
}
h[][x].push(tmp);
}
}
il int divi(int x,int d,int ff){
//cout<<" x d ff "<<x<<" "<<d<<" "<<ff<<endl;
rt=;
dfs1(x,,d);
fa[rt]=ff;
dis[rt][d]=;
dfs2(rt,,d); vis[rt]=;
ans[rt]=-inf;
int now=rt;
for(reg i=hd[now];i;i=e[i].nxt){
int y=e[i].to;
if(vis[y]) continue;
nowsz=sz[y];
int son=divi(y,d+,now); if(h[][son].size()){
h[][now].push(h[][son].top());
}
}
upda(now);
//cout<<" rt "<<now<<" : "<<ans[now]<<endl;
hh.push(ans[now]);
return now;
}
il void wrk(int x){
int gg=x;
int nd=dep[x];
if(c[x]==){
c[x]^=;
while(x){
//cout<<" xx nd "<<x<<" "<<nd<<" "<<endl;
dd.push(ans[x]);
clear(x,);
upda(x);
hh.push(ans[x]); if(fa[x]){
if(h[][x].size()) d[][fa[x]].push(h[][x].top());
d[][x].push(dis[gg][nd-]);
clear(x,);
if(h[][x].size()) h[][fa[x]].push(h[][x].top());
} x=fa[x];
--nd;
}
}
else{
c[x]^=;
while(x){
dd.push(ans[x]);
clear(x,);
upda(x);
hh.push(ans[x]); if(fa[x]){
if(h[][x].size()) d[][fa[x]].push(h[][x].top());
h[][x].push(dis[gg][nd-]);
clear(x,);
if(h[][x].size()) h[][fa[x]].push(h[][x].top());
} x=fa[x];
--nd;
}
}
}
int main(){
scanf("%d",&n);int x,y,z;
for(reg i=;i<=n-;++i){
rd(x);rd(y);rd(z);
add(x,y,z);add(y,x,z);
}
nowsz=n;
gen=divi(,,);
int m;
rd(m);
char ch[];
while(m--){
scanf("%s",ch+);
if(ch[]=='A'){ while(dd.size()&&hh.size()&&hh.top()==dd.top()){
hh.pop();dd.pop();
}
if(!hh.size()){
puts("They have disappeared.");
}
else{
int tmp=hh.top();
if(tmp==-inf) puts("They have disappeared.");
else {
(tmp<)&&(tmp=-tmp,putchar('-'));
prin(tmp);putchar('\n');
}
}
}else{
rd(x);
wrk(x);
}
// cout<<" ans------- "<<endl;
// for(reg i=1;i<=n;++i){
// cout<<i<<" : "<<ans[i]<<endl;
// }
}
return ;
} }
int main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/11/28 9:20:15
*/
你也可以顺带AC[ZJOI2007]捉迷藏
Qtree4——动态点分治的更多相关文章
- COJ 0346 WZJ的旅行(二)更新动态树分治版本
WZJ的旅行(二) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 时隔多日,WZJ又来到了幻想国旅行.幻想国由N个城市组成,由 ...
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...
- 【Learning】 动态树分治
简介 动态树分治整体上由点分治发展而来. 点分治是统计树上路径,而动态树分治用来统计与点有关的树上路径,比如多次询问某一些点到询问点的距离和. 前置知识就是点分治. 做法 众所周知,点分树(点分治中重 ...
- 【BZOJ4372】烁烁的游戏(动态点分治)
[BZOJ4372]烁烁的游戏(动态点分治) 题面 BZOJ 大意: 每次在一棵书上进行操作 1.将离某个点u的距离不超过d的点的权值加上w 2.询问单点权值 题解 这题和前面那一道震波几乎是一模一样 ...
- 【BZOJ3730】震波(动态点分治)
[BZOJ3730]震波(动态点分治) 题面 BZOJ 题意 给定一棵树, 每次询问到一个点的距离\(<=K\)的点的权值之和 动态修改权值, 强制在线 题解 正常的\(DP\)??? 很简单呀 ...
- 【BZOJ3924】幻想乡战略游戏(动态点分治)
[BZOJ3924]幻想乡战略游戏(动态点分治) 题面 权限题...(穷死我了) 洛谷 题解 考虑不修改 发现一个贪心的做法 假设当前放在当前位置 如果它有一个子树的兵的总数大于总数的一半 那么,放到 ...
- 【BZOJ1095】捉迷藏(动态点分治)
[BZOJ1095]捉迷藏(动态点分治) 题面 BZOJ 题解 动态点分治板子题 假设,不考虑动态点分治 我们来想怎么打暴力: \(O(n)DP\)求树的最长链 一定都会.不想解释了 所以,利用上面的 ...
- 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏
简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...
- [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)
题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...
随机推荐
- Django Rest Framework源码剖析(七)-----分页
一.简介 分页对于大多数网站来说是必不可少的,那你使用restful架构时候,你可以从后台获取数据,在前端利用利用框架或自定义分页,这是一种解决方案.当然django rest framework提供 ...
- POJ1080
一道字符串DP,然而不需要状压之类的玄学操作 题目大意:给你两个串,由'A','C','G','T'组成,现在你可以在这两个串中的某些位置插入'-',最终要使得它们的长度相等 给出两个字符匹配时的匹配 ...
- Luogu P3227 [HNOI2013]切糕
%%ZZKdalao上课讲的题目,才知道网络流的这种玄学建模 我们先想一想,如果没有D的限制,那么想当于再每一根纵轴上选一个权值最小的点再加起来 我们对应在网络流上就是每一根纵轴上的点向它下方的点用权 ...
- MySQL清理慢查询日志slow_log的方法
一.清除原因 因为之前打开了慢查询,导致此表越来越大达到47G,导致磁盘快被占满,使用xtrabackup进行备份的时候文件也超大. mysql> show variables like 'lo ...
- libgdx学习记录19——图片动态打包PixmapPacker
libgdx中,opengl 1.x要求图片长宽必须为2的整次幂,一般有如下解决方法 1. 将opengl 1.x改为opengl 2.0.(libgdx 1.0版本后不支持1.x,当然不存在这个问题 ...
- C语言和python的区别
Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作为大一新生的入门语言.本萌新也刚开 ...
- Redis基本数据类型介绍笔记
Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...
- 【转载】SSD断电保护原理
异常掉电的隐患 若没有合理的掉电保护机制,而异常掉电的发生又不可避免,当发生异常掉电,会引发很多问题. (1)丢盘 异常掉电,会使得映射表来不及保存,丢失逻辑地址到物理地址的映射,待重新上电后,SSD ...
- 二叉树 c++
树 非空树 有一个(root)根节点r 其余节点可分为m个互不相交的有限集(子树)T1....Tm 具有n个节点的树,具有(n-1)条连接(指针域),需要构成结构体,尽可能减少空间域的浪费,使用儿子兄 ...
- 搭建ZooKeeper
从http://zookeeper.apache.org/ 官网上下载最新的zookeeper版本, 我下载的版本是 zookeeper-3.4.6.tar.gz, 解压: 配置conf/zoo.cf ...