QTREE5 - Query on a tree V

动态点分治和动态边分治用Qtree4的做法即可。

LCT:

换根后,求子树最浅的白点深度。

但是也可以不换根。类似平常换根的往上g,往下f的拼凑

考虑深度的pushup必须考虑原树结构的联系,而ch[0],ch[1]又不是直接的前驱后继,每次pushup还要找前驱后继答案,还不如直接记下来。

故,节点里维护:

1.sz,大小

2.color节点颜色

3.set每个虚儿子贡献的最浅深度

4.lmn,rmn,当前x的splay子树最浅点和最深点的,展开成的实链的范围内的答案。

也就是:

pushup:

后面的就是跨过x的拼凑。top是虚儿子set的最小值

access:

虚实儿子转化

修改,access,splay,t[x].co^1

查询:access,splay, cout<<t[x].rmn

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &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);
}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=+;
const int inf=0x3f3f3f3f;
int n,q;
struct node{
int ch[],fa;
int lmn,rmn;
int co;//1:white 0:black
int sz;
multiset<int>s;
multiset<int>::iterator it;
int top(){
if(s.size()) return *s.begin();
return inf;
}
void ins(int c){
s.insert(c);
}
void dele(int c){
it=s.lower_bound(c);
if(it!=s.end()) s.erase(it);
}
void op(){
cout<<" ch[0] "<<ch[]<<" ch[1] "<<ch[]<<" fa "<<fa<<endl;
cout<<" co "<<co<<" sz "<<sz<<endl;
cout<<" lmn "<<lmn<<" rmn "<<rmn<<endl;
cout<<" s.size() "<<s.size()<<endl;
}
}t[N];
int nrt(int x){
return t[t[x].fa].ch[]==x||t[t[x].fa].ch[]==x;
}
void pushup(int x){
if(!x) return;
t[x].sz=t[t[x].ch[]].sz+t[t[x].ch[]].sz+;
t[x].lmn=min(t[t[x].ch[]].lmn,t[t[x].ch[]].sz+min(t[x].co?:inf,min(t[x].top(),t[t[x].ch[]].lmn+)));
t[x].rmn=min(t[t[x].ch[]].rmn,t[t[x].ch[]].sz+min(t[x].co?:inf,min(t[x].top(),t[t[x].ch[]].rmn+)));
}
void rotate(int x){
int y=t[x].fa,d=t[y].ch[]==x;
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
else t[x].fa=t[y].fa;
t[t[x].ch[!d]=y].fa=x;
pushup(y);
}
void splay(int x){
int y,z;
while(nrt(x)){
y=t[x].fa,z=t[y].fa;
if(nrt(y)){
rotate((t[y].ch[]==x)==(t[z].ch[]==y)?y:x);
}
rotate(x);
}
pushup(x);
}
void access(int x){
// cout<<" access "<<x<<endl;
for(reg y=;x;y=x,x=t[x].fa){
splay(x);
if(y) t[x].dele(t[y].lmn+);
if(t[x].ch[]) t[x].ins(t[t[x].ch[]].lmn+);
t[x].ch[]=y;
pushup(x);
// cout<<" x "<<x<<" y "<<y<<endl;
// t[x].op();
}
}
struct edge{
int nxt,to;
}e[*N];
int hd[N],cnt;
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
void dfs(int x,int fa){
t[x].sz=;
t[x].lmn=inf;t[x].rmn=inf;
t[x].co=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa) continue;
t[y].fa=x;
dfs(y,x);
}
}
int main(){
rd(n);
int x,y;
for(reg i=;i<n;++i){
rd(x);rd(y);
add(x,y);add(y,x);
}
dfs(,);
rd(q);
int op;
t[].lmn=inf,t[].sz=;
t[].rmn=inf;t[].co=;
while(q--){
rd(op);rd(x);
if(!op){
access(x);splay(x);
t[x].co^=;
pushup(x);
// t[x].op();
}else{
access(x);splay(x);
// t[x].op();
printf("%d\n",t[x].rmn<=n?t[x].rmn:-);
}
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/3/14 21:49:23
*/

见着拆招,pushup不好处理,就直接记录lmn和rmn,lmn用于access更新set,rmn用于查询答案。

如果要换根,还要考虑swap(lmn,rmn)

QTREE5 - Query on a tree V——LCT的更多相关文章

  1. QTREE5 - Query on a tree V(LCT)

    题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...

  2. SPOJ - QTREE5 Query on a tree V 边分治

    题目传送门 题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少. 题解: 这里用的还是边分治的方法. 把所有东西都抠 ...

  3. SPOJ QTREE Query on a tree V

    You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are number ...

  4. SPOJ Query on a tree V

    You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are number ...

  5. SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块

    \(\color{#0066ff}{ 题目描述 }\) 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v ...

  6. 2019.02.17 spoj Query on a tree V(链分治)

    传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...

  7. [spojQTREE5]Query on a tree V

    合理的正解大概是动态点分治,这里给出其实现 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 st ...

  8. SPOJ QTREE Query on a tree V ——动态点分治

    [题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...

  9. spoj 375 query on a tree LCT

    这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的). ...

随机推荐

  1. Highgo 瀚高数据库的简单搭建以及处理参数等.

    1. 获取一个瀚高数据库的安装文件 我这边只获取了 瀚高的 2.0.4 的windows x64 版本的. 来源: 同事从供应商那里获取的. 2. windows上面简单安装 很简单 exe 一路ne ...

  2. [转帖]整理:Windows系统下的奇技淫巧大汇总

    整理:Windows系统下的奇技淫巧大汇总 https://blog.csdn.net/bat67/article/details/76381357 Win+home Crtl+home 还有 Win ...

  3. Mybatis Dao层注解及XML组合Dao的开发方式

    mybatis可以用xml进行数据操作,也可以在dao层用注解的方式,也可以采取xml和dao层接口组合使用的方法.显然 ,后者更加简单. 实体类Student   package com.zhao. ...

  4. CentOs7安装docker(第二篇)

    一.Docker的概念: Docker: 镜像:Images 类似于面向对象中的类 容器:Container 类似于面向对象中的对象 它们之间的关系:容器Container通过镜像Images来创建 ...

  5. Django Rest framework 框架

    一.开发模式: 1. 普通开发方式(前后端放在一起写) 2. 前后端分离(前后台通过ajaxo交互) 后端(django rest framework写的) <----ajaxo---> ...

  6. python之路--前端CSS

    一.CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义了如何显示HTML元素,给HTML设置样式,让他更加美观. 当浏览器读到这个样式表, 他就会按照这个样式来对文档进行 ...

  7. 离线安装redis-cluster

    #离线安装redis-cluster https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz #安装ruby .tar.gz cd rub ...

  8. Python——Django-应用的models.py内容

    一.数据的相关配置 #数据库的相关配置 DATABASE = { 'default':{ #连接的数据库类型 'ENGINE':'django.db.backends.sqlite3', #连接数据库 ...

  9. python 基础篇

    1.编程语言介绍. 1.机器语言:直接用二进制编程,直接对硬件的控制,需对硬件掌握比较深. 优点:执行效率快 缺点:开发效率低下 2.汇编语言:用英文标签代替二进制编写程序,直接对硬件的控制,需对硬件 ...

  10. Vue数组更新及过滤排序

    前面的话 Vue为了增加列表渲染的功能,增加了一组观察数组的方法,而且可以显示一个数组的过滤或排序的副本.本文将详细介绍Vue数组更新及过滤排序 变异方法 Vue 包含一组观察数组的变异方法,它们将会 ...