qtree4
https://zybuluo.com/ysner/note/1236834
题面
给出一棵边带权的节点数量为\(n\)的树,初始树上所有节点都是白色。有两种操作:
- 改变节点\(x\)的颜色,即白变黑,黑变白
- 询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为\(0\))。
\(n\leq10^5,q\leq2*10^5\)
解析
打这道题的过程中,\(get\)了许多新姿势。
点分治经典问题。每次分治时找到每棵子树深度最大的一个白点,用最大的两个统计一下即可。
找最大和次大自然需要堆,且每个点都需要开两个。
第一个堆插入这个重心管辖的一坨树所有白点到分治树上这个点父亲的距离。
第二个堆插入所有点分治树上孩子的堆顶,这样我们就可以对于每个分治重心,找到分属两棵子树的深度最大的两个白点,即这个点堆的最大和次大值。
修改就只要再点分树上从自己的重心往根走,然后维护一下那些堆。
注意这些堆要可删除(即可以指定删除其中一个元素)。
原理是每个堆里设一个删除堆和插入堆,插入元素就插入插入堆,删除元素就插入删除堆。如要取堆顶,就把两堆同时弹到堆顶不相等即可,取插入堆堆顶即可。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define inf 1000000000
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=5e5+100;
struct Edge{int to,nxt,w;}e[N<<1];
struct dui
{
priority_queue<int>s,t;int sz;
il void pop(re int x){t.push(x);--sz;}
il void push(re int x){s.push(x);++sz;}
il void pre(){while(t.size()&&s.top()==t.top()) s.pop(),t.pop();}
il int top(){pre();return sz?s.top():-inf;}
il int len()
{
if(sz<2) return 0;
re int x=top();pop(x);
re int y=top();push(x);
return max(x+y,0);
}
il void del(re int x,re int k){k?pop(x):push(x);}
}a[N],b[N],ans;
int n,h[N],cnt,Q,d[N],dis[N],f[N],sz[N],mx,mn,Sz[N],top[N],son[N],root,Size,F[N],w[N],tot,s[N],tim;
bool vis[N];
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void dfs1(re int u,re int fa)
{
d[u]=d[fa]+1;f[u]=fa;sz[u]=1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa) continue;
dis[v]=dis[u]+e[i].w;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
il void dfs2(re int u,re int up)
{
top[u]=up;
if(son[u]) dfs2(son[u],up);
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
il int lca(re int u,re int v)
{
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]]) swap(u,v);
u=f[top[u]];
}
return d[u]<d[v]?u:v;
}
il int Dis(re int u,re int v){return dis[u]+dis[v]-2*dis[lca(u,v)];}
il void Getrt(re int u,re int fa)
{
re int mx=0;Sz[u]=1;s[++tim]=u;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa||vis[v]) continue;
Getrt(v,u);
Sz[u]+=Sz[v];
mx=max(mx,Sz[v]);
}
mx=max(mx,Size-Sz[u]);
if(mx<mn) mn=mx,root=u;
}
il int dfs(re int u,re int fa)
{
vis[u]=1;F[u]=fa;b[u].push(0);
if(F[u]) fp(i,1,tim) a[u].push(Dis(s[i],F[u]));
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(vis[v]) continue;
Size=Sz[v];mn=n;tim=0;
Getrt(v,u);
re int p=dfs(root,u);
b[u].push(a[p].top());
}
ans.push(b[u].len());
return u;
}
il void Modify(re int u,re int w)
{
re int l1=b[u].len(),l2,s1,s2;
b[u].del(0,w);l2=b[u].len();
if(l1^l2) ans.pop(l1),ans.push(l2);
for(re int i=u;F[i];i=F[i])
{
s1=a[i].top();
a[i].del(Dis(u,F[i]),w);
s2=a[i].top();
if(s1==s2) continue;
l1=b[F[i]].len();
if(s1!=-inf) b[F[i]].pop(s1);if(s2!=-inf) b[F[i]].push(s2);
l2=b[F[i]].len();
if(l1^l2) ans.pop(l1),ans.push(l2);
}
}
int main()
{
memset(h,-1,sizeof(h));
tot=n=gi();
fp(i,1,n-1)
{
re int u=gi(),v=gi(),w=gi();
add(u,v,w);add(v,u,w);
}
dfs1(1,0);dfs2(1,1);
Size=mn=n;Getrt(1,0);
dfs(root,0);
fp(i,1,n) w[i]=1;
Q=gi();
while(Q--)
{
re char op='0';while(op!='A'&&op!='C') op=getchar();
if(op=='A')
{
tot?printf("%d\n",tot==1?0:ans.top()):puts("They have disappeared.");
}
if(op=='C')
{
re int u=gi();tot+=(w[u]?-1:1);
Modify(u,w[u]);w[u]^=1;
}
}
return 0;
}
qtree4的更多相关文章
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...
- luogu P4115 Qtree4
题目链接 luogu P4115 Qtree4 题解 动态点分治,和上一题一样.同样三个堆.就是带权,用边权替换深度就好 为什么要单独写这个题解呢,因为我卡常卡了一天....据说树剖比rmq快? 在第 ...
- SPOJ2666 QTREE4
我是萌萌的传送门 我是另一个萌萌的传送门 一道树分治……简直恶心死了……我在调代码的时候只想说:我*************************************************…… ...
- 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV
意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...
- SPOJ QTREE4 lct
题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #i ...
- 洛谷 4115 Qtree4——链分治
题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...
- Qtree4——动态点分治
题目描述 给出一棵边带权的节点数量为n的树,初始树上所有节点都是白色.有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为 ...
- luoguP4115 QTREE4 链分治
具体看$qzc$论文吧......陈年老物了...... 主要注意每个链头一棵线段树而不是一棵全局线段树 修改操作写完就是正确的,反而是初始化调了好一会...... 跑的还是很快的,有些地方没优化常数 ...
- SP2666 QTREE4 - Query on a tree IV(LCT)
题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...
- SPOJ QTREE4 SPOJ Query on a tree IV
You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3. ...
随机推荐
- 梦想CAD控件自定义实体实现
一.增加自定义实体对象 调用DrawCustomEntity函数,绘制一个自定义实体对象. 下面代码绘制一个自定义实体,C#代码实现如下: private void DrawMlineCommand( ...
- vue+axios上传文件
单独上传文件: <input class="file" name="file" type="file" accept="im ...
- 生成count个[0-n)不重复的随机数
代码来自:https://www.cnblogs.com/ningvsban/p/3590722.html,感觉实现的方式不错(做了一点小小修改) public static ArrayList ge ...
- java虚拟机(七)--java内存模型JMM
本文参考慕课网相关视频和博客https://mp.weixin.qq.com/s/tV0MfDdJqGwGMHCIkqnAgA,图也是这个博客的,这篇只是自己的简单总结,想要深 入理解可以访问这两块内 ...
- vue基础---介绍
(1)声明式渲染 Vue.js 的核心是采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统: ①文本 <div id="app"> {{ message }} & ...
- thupc & cts & apio & thusc 游记 (北京17日游记)
thupc & cts & apio & thusc 游记 (北京17日游记) Day 0 和隔壁校两人py了一下,六个人组了两队,(左哼哼)与(右哼哼),我和Camoufla ...
- javaScript--进阶1--数据类型、操作符
一.JS基础知识背景 1.1 弱类型脚本语言 脚本语言是:弥补编译语言的不足而存在的,作为补充语言,不用编译,解析一行执行一行. 弱类型语言:简单理解定义一个变量,可以有多种数据类型.(var tem ...
- UVA - 1623 Enter The Dragon(贪心)
题目: 思路: 读完题之后有了以下想法: 当遇到下雨的天,就找这个湖泊上一次下雨满了之后又一次不下雨的日期.有就在这个日期下记录被神龙喝干的湖的编号,没有就是不符合题意. 这个想法是对的,但是却被代码 ...
- Java核心技术 卷一 复习笔记(乙
1.字符串从概念上讲,Java字符串就是Unicode字符序列.Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,叫String. 每个用双引号括起来的字符串都是 String ...
- Python基础—面向对象(进阶篇)
通过上一篇博客我们已经对面向对象有所了解,下面我们先回顾一下上篇文章介绍的内容: 上篇博客地址:http://www.cnblogs.com/phennry/p/5606718.html 面向对象是一 ...