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. 10 Useeful Tips for Writing Effective Bash Scripts in Linux

    1.Always Use Comments in Scripts2.Make a Scripts exit When Fails    Sometimes bash may continue to e ...

  2. Android音视频点/直播模块开发实践总结-zz

    随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...

  3. F5后端nginx+tomcat应用如何获得用户的真实ip【转】

    根据业务需要要求记录每个通过wap或者客户端访问我们服务器的用户真实ip但是由于业务前端部署了两个3900系列的F5设备导致程序一直获得F5设备自身的ip,所以笔者考虑可能是因为F5导致无法获得用户的 ...

  4. 去除TFS版本控制

    对于曾经做过TFS版本控制的项目,在版本控制服务不可用的时候,依然会在每次打开项目的时候都提示:当前项目是版本控制的项目,但是当前版本控制不可用,balabala的信息,如果是需要进行版本控制的项目在 ...

  5. 新浪的wap网站,发现原来我们的head存在着这样的差异

    前一段时间一直被wap网站的自适应困惑…… 仔细研究了一下新浪的wap网站,发现原来我们的head存在着这样的差异…… <%@page contentType="text/html;c ...

  6. linux系统时钟和硬件时钟不一致

    在做DB2 集群复制的时候要求两台主机时间相互一致. 但是在一台主机上系统时间和硬件时间相差12个小时左右:手动同步后,重启后又相差12个小时左右. 为什么会是这样的,先介绍下系统时钟和硬件时钟的区别 ...

  7. RabbitMQ--work queues(二)

    封装一个task到一个message,并发送到queue.consumer会去除task并执行这个task. 这里我们简化了操作,发送消息到队列中,consumer取出消息计算里面'.'号有几个就sl ...

  8. ASP .NET Core 2.0 MVC 发布到 IIS 上以后 无法下载apk等格式的文件

    ASP .NET Core MVC 发布到  IIS 上以后 无法下载apk等格式的文件 使用.NET Core MVC创建了一个站点,其他文件可以下载,但是后来又需求,就把手机端的apk合适的文件上 ...

  9. CentOS下编译安装python包管理安装工具pip教程

    ubuntu 安装pip 代码如下: apt-get install python-pip 安装requests, pip install requests 对于centos的,直接 yum inst ...

  10. who am i ?

    Id:Ox9A82 Email:hucvbty@gmail.com 微博:http://weibo.com/1828621423 知乎:Ox9A82 常乐村男子职业技术学院 Syclover拖后腿成员 ...