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} ...
随机推荐
- 20155302《网络对抗》Exp3 免杀原理与实践
20155302<网络对抗>Exp3 免杀原理与实践 实验要求 1.正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编 ...
- Luogu P1726 上白泽慧音
这显然是一道求强连通分量(SCC)的题目. 只要你正常,都知道应该写Tarjan. 然后(假装会写Tarjan),其实我当然不会.但是求SCC还有另一个算法.复杂度和Tarjan一样,只不过常数大了点 ...
- C# Language Specification 5.0 (翻译)第五章 变量
变量(variable)表示存储的位置.每个变量都有类型,类型决定变量保存的值的类型.C# 是一门类型安全的语言,C# 编译器会确保变量中保存一个适合类型的值.变量的值可通过赋值或通过使用 ++ 与 ...
- jQuery .attr() vs. .prop()
Property vs. Attribute 在开始正式比较prop()和attr()两个jQuery方法之前,我们有必要先弄清一下Property和Attribute两个单词的意思.在中文里面,它们 ...
- effective c++ 笔记 (26-29)
//---------------------------15/04/09---------------------------- //#26 尽可能延后变量定义式的出现时间 { /* 1:只要 ...
- JMeter:生成漂亮的接口/压力测试的HTML报告
JMeter生成HTML网页报告(非gui模式操作) 我们做性能测试的时候会经常使用一些性能测试工具,比如loardrunner和jmeter,我个人比较喜欢Jmeter这个工具,jmeter之前版本 ...
- Unity导入模型出现 (Avatar Rig Configuration mis-match. Bone length in configuration does not match position in animation)?
昨天遇到这两个模型导入的问题,查了一下资料,自己摸索了一下解决方法..总结一下~ 出现的原因:(问题1)Warning 当模型文件导入以后并且设置Animation Type是Generic的时候,动 ...
- Unity3D Shader 学习笔记(一):初识Shader
第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...
- PAT甲题题解-1064. Complete Binary Search Tree (30)-中序和层次遍历,水
由于是满二叉树,用数组既可以表示父节点是i,则左孩子是2*i,右孩子是2*i+1另外根据二分搜索树的性质,中序遍历恰好是从小到大排序因此先中序遍历填充节点对应的值,然后再层次遍历输出即可. 又是一道遍 ...
- Linux第一章第二章学习笔记
第一章 Linux内核简介 1.1 Unix的历史 它是现存操作系统中最强大最优秀的系统. 设计简洁,在发布时提供原代码. 所有东西都被当做文件对待. Unix的内核和其他相关软件是用C语言编写而成的 ...