维护信息的方式十分巧妙~

维护每一棵 splay 中深度最浅,深度最深的点距离最近的白点.

这样非常方便维护,进行区间合并,进行子树维护

很多时候在维护东西的时候最大/最小/深度最小/深度最大会相对容易维护,所以如果用树剖/LCT维护信息时发现很难维护的话可以采用这种套路.

因为动态树是可以维护子树信息的,也可以 ​,所以如果维护深度最深的信息的话只需 ​ 就可以做到.

code:

#include <bits/stdc++.h>
#define N 100006
#define inf 1000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,edges;
int hd[N],to[N<<1],nex[N<<1],col[N];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
struct Link_Cut_Tree
{
#define lson p[x].ch[0]
#define rson p[x].ch[1]
struct Node
{
int ch[2],f,size,lmn,rmn;
multiset<int>s;
int get() { return s.empty()?inf:*s.begin(); }
}p[N];
int get(int x) { return p[p[x].f].ch[1]==x; }
int isrt(int x) { return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x); }
void pushup(int x)
{
p[x].size=p[lson].size+p[rson].size+1;
p[x].lmn=min(p[lson].lmn, p[lson].size+min(col[x]?0:inf, min(p[x].get(), p[rson].lmn+1)));
p[x].rmn=min(p[rson].rmn, p[rson].size+min(col[x]?0:inf, min(p[x].get(), p[lson].rmn+1)));
}
void rotate(int x)
{
int old=p[x].f,fold=p[old].f,which=get(x);
if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;
p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old;
p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold;
pushup(old),pushup(x);
}
void splay(int x)
{
int u=x,v=0,fa;
for(;!isrt(u);u=p[u].f);
for(u=p[u].f;(fa=p[x].f)!=u;rotate(x))
if(p[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=p[x].f)
{
splay(x);
if(rson)
{
p[x].s.insert(p[rson].lmn+1);
}
if(y)
{
p[x].s.erase(p[x].s.find(p[y].lmn+1));
}
rson=y;
pushup(x);
}
}
#undef lson
#undef rson
}lct;
void dfs(int u,int ff)
{
lct.p[u].f=ff;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dfs(v,u);
lct.p[u].s.insert(inf+1);
}
lct.pushup(u);
}
int main()
{
// setIO("input");
int i,j;
scanf("%d",&n);
for(i=1;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
lct.p[0].lmn=lct.p[0].rmn=inf;
dfs(1,0);
int m;
scanf("%d",&m);
for(i=1;i<=m;++i)
{
int op,u;
scanf("%d%d",&op,&u);
if(op==0)
{
lct.Access(u);
lct.splay(u);
col[u]^=1;
lct.pushup(u);
}
else
{
lct.Access(u);
lct.splay(u);
printf("%d\n",lct.p[u].rmn>n?-1:lct.p[u].rmn);
}
}
return 0;
}

  

SPOJ 2939 QTREE5 LCT的更多相关文章

  1. SPOJ QTREE5 lct

    题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set ...

  2. QTREE5 - Query on a tree V——LCT

    QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...

  3. spoj 375 query on a tree LCT

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

  4. SPOJ OTOCI 动态树 LCT

    SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...

  5. SPOJ - OTOCI LCT

    OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem. ...

  6. SPOJ QTREE4 lct

    题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #i ...

  7. SPOJ QTREE3 lct

    题目链接 题意: 给定n个点 q个询问 以下n-1行给出树边,点有黑或白色.初始化为白色 以下q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑 ...

  8. SPOJ QTREE2 lct

    题目链接 题意: 给一棵树.有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstrea ...

  9. SPOJ2939 QTREE5(LCT维护子树信息)

    QWQ嘤嘤嘤 此题正规题解应该是边分治??或者是树剖(总之不是LCT) 但是我这里还是把它当成一个LCT题目来做 首先,这个题的重点还是在update上 因为有\(makeroot\)这个操作的存在, ...

随机推荐

  1. 小白入门.有函数F(x)=(x+1)^2和G(x)=2x+1.输入x值计算F(G(x))。

    #include<stdio.h> #include<math.h> void main() { float x,y; printf("Please input x\ ...

  2. k8s安装ingress

    1. 环境准备 安装nginx-ingress-controller和backend cd /etc/yum.repos.d/mainfests 下载镜像的脚本 vi ingressnginx.sh ...

  3. vue 写一个炫酷的轮播图

    效果如上图: 原理: 1.利用css 的 transform 和一些其他的属性,先选五张将图片位置拍列好,剩余的隐藏 2.利用 js 动态切换类名,达到切换效果 css代码如下 .swiper-cer ...

  4. 将double转化成string,并保持N位小数

    double dumpSize = (1024000000.1415926535897932384 * 1.0) / 1024 / 1024; string tempStr = to_string(d ...

  5. C# List 转 Tree 公共方法

    # 用C# 写了个List数据结构转树形数据结构的公共扩展方法 /// <summary> /// 将列表转换为树形结构 /// </summary> /// <type ...

  6. C#数字日期转成中文日期

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  7. 3_PHP表达式_1_常量

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. PHP常量分为自定义常量与预定义常量. 1.自定义常量 在使用前必须先定义,PHP的define()函数专门用于定 ...

  8. 1+x证书学习日志——css 基本选择符

    ##css选择符                 1:类型选择符 直接用标签名称当作选择符                     特点:选中所有同类元素                 2:id名称 ...

  9. vue滚动分页加载以及监听事件处理

    <template> <div class="bodyContainer"> <div class="allContent" id ...

  10. OpenStack kilo版(6) 启动第一台虚拟机

    创建网络 提供者为external,类型为flat,网络名称为public,: root@controller:~# neutron net-create --shared --provider:ph ...