http://www.lydsy.com/JudgeOnline/problem.php?id=4573

http://blog.csdn.net/lych_cys/article/details/53515748#

lct的难点大概是转换的部分。

这道题需建两种权值不同的点,每次更换生长节点建立权值为0的虚点,生长新点建立权值为1的实点,因为最开始有一个带权值的生长节点,那么建一个虚点一个实点来表示。

因为求的东西追根溯源只是链,每棵树从根到某点的链的结构都是交错的所以可以这样压缩点以及点点之间的关系。

实点需要连向最近建立的虚点,虚点需要连向最近建立的实点,注意一下离线前虚点被连成一条链,离线操作时某一个控制范围结束也是将这个虚点连回原来的链上。

按照操作的树的起始位置和操作时间排序,就可以离线处理了。这个离线操作大概可以视为几个实点虚点交错的链两端断开连接。

计算距离lca实现,两次access+splay计算的两个点x和y到根的距离和,他们的lca其实是 access y 的时候的最后一个连通块的入点,这个应该想一下可以想到。

access lca的时候我才发现access是删掉整个右子树的,这样操作顺利删掉了y到lca的这段距离。(原来以前都没有意识到access的原理么我果然是个傻子)。

注释什么的代码里解释的很详细了。

过了157个人,时间空间排名83竟然有点开心(还有74个人想的板子没有我抄的板子快呀(有毒))。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=;
int n,m;
int ch[maxn][]={},fa[maxn]={},siz[maxn]={};//splay相关
int sum[maxn]={},num[maxn]={};//splay子树和,点值(0/1)
int l[maxn]={},r[maxn]={};//对实点的记录,每个实点存在的树的标号范围
int b[maxn]={};//编号为i的实点的编号为b[i]
int tly=,cnt=;//tly是对点数的记录,cnt表示当前生成到编号为cnt的实点
int ans[maxn]={};
struct nod{
int z,ti,x,y;//操作的树的序号 操作时间(排序的一个依据) 需要连的两个点
}a[maxn*];int tot=;
bool mcmp(nod aa,nod bb){ return aa.z<bb.z||(aa.z==bb.z&&aa.ti<bb.ti); }
//离线操作是先按位置后按地点的方式排列的。
inline bool isroot(int x){ return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline void updata(int x){ sum[x]=sum[ch[x][]]+sum[ch[x][]]+num[x];}
inline void newp(int v){ tly++;num[tly]=sum[tly]=v; }
inline void init(int z,int ti,int x,int y){
a[++tot].z=z;a[tot].ti=ti;a[tot].x=x;a[tot].y=y;
}
void rotate(int x){
int y=fa[x];int fy=fa[y];
int l=ch[y][]==x?:;int r=l^;
if(!isroot(y)){
if(ch[fy][]==y) ch[fy][]=x;
else ch[fy][]=x;
}
fa[ch[x][r]]=y; fa[x]=fy; fa[y]=x;
ch[y][l]=ch[x][r]; ch[x][r]=y;
updata(y);
}
void splay(int x){
while(!isroot(x)){
int y=fa[x];int fy=fa[y];
if(!isroot(y)){
if((ch[y][]==x)^(ch[fy][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}updata(x);
}
int access(int x){
int y=;
while(x){
splay(x);
ch[x][]=y;
updata(x);
y=x;x=fa[x];//这里的y和上面的含义不同,这里的是儿子。
}return y;
}
void cut(int x){
access(x);splay(x);
fa[ch[x][]]=;ch[x][]=;updata(x);
}
void link(int x,int y){ cut(x);fa[x]=y;}
int main(){
scanf("%d%d",&n,&m);
newp();cnt=;b[]=l[]=;r[]=n;
newp();fa[]=;
int x,y,z,f;int now=;
for(int i=;i<=m;i++){
scanf("%d",&f);
if(!f){
cnt++;
scanf("%d%d",&l[cnt],&r[cnt]);
newp();b[cnt]=tly;
init(,i-m,tly,now);//操作的树的序号 时间(排序的两个依据) 需要连的两个点
}
else if(f==){
scanf("%d%d%d",&x,&y,&z);
x=max(x,l[z]);y=min(y,r[z]);
if(x<=y){
newp();
if(x>)fa[tly]=now;
init(x,i-m,tly,b[z]);
init(y+,i-m,tly,now);
now=tly;
}
}
else{
scanf("%d%d%d",&z,&x,&y);
init(z,i,b[x],b[y]);
}
}
sort(a+,a++tot,mcmp);
memset(ans,-,sizeof(ans));
int j=;
for(int i=;i<=n;i++){
for(;j<=tot&&a[j].z==i;j++){
if(a[j].ti>){
access(a[j].x);splay(a[j].x);
ans[a[j].ti]=sum[a[j].x];
x=access(a[j].y);
splay(a[j].y);
ans[a[j].ti]+=sum[a[j].y];
access(x);splay(x);
ans[a[j].ti]-=sum[x]*; }
else{
link(a[j].x,a[j].y);
}
}
}for(int i=;i<=m;i++)if(ans[i]!=-)printf("%d\n",ans[i]);
return ;
}

bzoj 4573: [Zjoi2016]大森林 lct splay的更多相关文章

  1. 【刷题】BZOJ 4573 [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...

  2. bzoj 4573: [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...

  3. [ZJOI2016]大森林(LCT)

    题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y掌握了一种 ...

  4. 洛谷P3348 [ZJOI2016]大森林 [LCT]

    传送门 刷了那么久水题之后终于有一题可以来写写博客了. 但是这题太神仙了我还没完全弄懂-- upd:写完博客之后似乎懂了. 思路 首先很容易想到\(O(n^2\log n)\)乘上\(O(\frac{ ...

  5. BZOJ4573:[ZJOI2016]大森林——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=4573 https://www.luogu.org/problemnew/show/P3348#sub ...

  6. [ZJOI2016]大森林

    Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例 ...

  7. P3348 [ZJOI2016]大森林

    \(\color{#0066ff}{ 题目描述 }\) 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点, ...

  8. 【LuoguP3348】[ZJOI2016]大森林

    题目链接 题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y ...

  9. UOJ#195. 【ZJOI2016】大♂森林 LCT

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ195.html 题解 首先询问都可以放到最后处理. 对于操作,我们把它差分一下离线下来. 现在的问题就是从 ...

随机推荐

  1. Linux/Unix系统编程手册 第二章:基本概念

    本章预热与后续系统编程有关的概念. 术语“操作系统”通常包含2种含义:一是指完整的软件包,包括管理计算机资源的核心组件,已经附带的标准软件:二是独指管理硬件的内核. 内核具有诸多概功能,包括: 进程管 ...

  2. XSS报警机制(前端防火墙:第二篇)

    XSS报警机制(前端防火墙:第二篇) 在第一章结尾的时候我就已经说了,这一章将会更详细的介绍前端防火墙的报警机制及代码.在一章出来后,有人会问为什么不直接防御,而是不防御报警呢.很简单,因为防御的话, ...

  3. 【连接查询】mySql多表连接查询与union与union all用法

    1.准备两个表 表a: 结构: mysql> desc a; +-------+-------------+------+-----+---------+-------+ | Field | T ...

  4. idea心得

    概述 Intellij IDEA真是越用越觉得它强大,它总是在我们写代码的时候,不时给我们来个小惊喜.出于对Intellij IDEA的喜爱,我决定写一个与其相关的专栏或者系列,把一些好用的Intel ...

  5. sublime Text快捷键(超级全)

    sublime Text快捷键(超级全) Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W: ...

  6. Linux下堆漏洞的利用机制

    1.保护机制 )) malloc_printerr (check_action, "corrupted double-linked list", P); 这个就是所谓的堆指针的ch ...

  7. Python的简单语法(一)

    import sys a=3 b=4 c=5.66 d=8.0 e=complex(c,d) f=complex(float(a),float(b)) print("a is type:&q ...

  8. java对象与xml相互转换工具类

    public class XmlHelper { /** * Object转XML * * @param object * @return * @throws Exception */ public ...

  9. Nginx 虚拟主机 VirtualHost 配置

    Nginx 是一个轻量级高性能的 Web 服务器, 并发处理能力强, 对资源消耗小, 无论是静态服务器还是小网站, Nginx 表现更加出色, 作为 Apache 的补充和替代使用率越来越高. 我在& ...

  10. CentOS7.5之Sqoop1.4.7的安装使用

    一 Sqoop简介 Apache Sqoop(TM) 于 2012 年 3 月孵化出来,现在是一个顶级的 Apache 项目.是一种旨在有效地在 Apache Hadoop 和诸如关系数据库等结构化数 ...