题目描述

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

小Y掌握了一种魔法,能让第l棵树到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?

题解

这题太神了,废了我一下午。

看到区间操作,就可以想到差分或者扫描线,我们会发现这题基本没有好的方法去执行批量操作,所以我们要用扫描线。

这道题的操作有,区间生长一个点,区间换父亲。

我们对于每个1操作新建一个虚点,然后把它们串起来,然后把每个0操作长出来的点挂在上一个虚点上,然后一通做完之后的树长这样(白点为虚点,黑点为实点)。

时间从上到下为从早到晚。

对于一个换父亲操作,假如说我们要对最下面的白点对应的换父亲的操作换到右边从上到下第二个黑点上,那么我们可以这样。

可以手玩一下,所有有效节点对应的deep是对的。

然后我们用LCT维护这一过程,求两点

注意判断1操作的作用范围。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 200002
using namespace std;
int tr[N][],fa[N],size[N],w[N],cnt,n,m,tot,top,b[N],L[N],R[N],ji[N],qqq,ans,ans2[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline bool isroot(int x){return !x||(tr[fa[x]][]!=x&&tr[fa[x]][]!=x);}
inline bool ge(int x){return tr[fa[x]][]==x;}
inline void pushup(int x){size[x]=size[tr[x][]]+size[tr[x][]]+w[x];}
inline void newnode(int x){++cnt;w[cnt]=size[cnt]=x;}
inline void rotate(int x){
int y=fa[x],o=ge(x);
if(isroot(x))return;
tr[y][o]=tr[x][o^];fa[tr[y][o]]=y;
if(!isroot(y))tr[fa[y]][ge(y)]=x;fa[x]=fa[y];
fa[y]=x;tr[x][o^]=y;
pushup(y);pushup(x);
}
inline void splay(int x){
while(!isroot(x)){
int y=fa[x];
if(isroot(y))rotate(x);
else rotate(ge(y)==ge(x)?y:x),rotate(x);
}
}
inline int access(int x){int y=;for(;x;y=x,x=fa[x])splay(x),tr[x][]=y,pushup(x);return y;}//qiu LCA get
inline void link(int x,int y){access(x);splay(x);fa[x]=y;}
inline void cut(int x){access(x);splay(x);fa[tr[x][]]=;tr[x][]=;pushup(x);}
struct node{
int pos,tag,x,y;
inline bool operator <(const node &b)const{
if(pos!=b.pos)return pos<b.pos;
else return tag<b.tag;
}
}a[N<<];
int main(){
n=rd();m=rd();int opt,l,r,k;
newnode();newnode();link(,);
int now=;b[tot=]=;L[tot]=;R[tot]=n;
for(int i=;i<=m;++i){
opt=rd();
if(!opt){
l=rd();r=rd();newnode();
b[++tot]=cnt;L[tot]=l;R[tot]=r;
a[++top]=node{,i-N,cnt,now};
}
else if(opt==){
l=rd();r=rd();k=rd();l=max(l,L[k]);r=min(r,R[k]);
if(l>r)continue;
newnode();link(cnt,now);
a[++top]=node{l,i-N,cnt,b[k]};a[++top]=node{r+,i-N,cnt,now};
now=cnt;
}
else{
k=rd();l=rd();r=rd();ji[i]=++qqq;
a[++top]=node{k,i,b[l],b[r]};
}
}
sort(a+,a+top+);int p=;
for(int i=;i<=n;++i)
for(;a[p].pos==i;++p)
if(a[p].tag<=){cut(a[p].x);link(a[p].x,a[p].y);}
else{
ans=;
access(a[p].x);splay(a[p].x);ans+=size[a[p].x];
int lca=access(a[p].y);splay(a[p].y);ans+=size[a[p].y];
access(lca);splay(lca);ans-=size[lca]*;
ans2[ji[a[p].tag]]=ans;
}
for(int i=;i<=qqq;++i)printf("%d\n",ans2[i]);
return ;
}

[ZJOI2016]大森林(LCT)的更多相关文章

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

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

  2. bzoj 4573: [Zjoi2016]大森林 lct splay

    http://www.lydsy.com/JudgeOnline/problem.php?id=4573 http://blog.csdn.net/lych_cys/article/details/5 ...

  3. [ZJOI2016]大森林

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

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

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

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

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

  6. P3348 [ZJOI2016]大森林

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

  7. bzoj 4573: [Zjoi2016]大森林

    Description 小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. React Native之微信分享(iOS Android)

    React Native之微信分享(iOS Android) 在使用React Native开发项目的时候,基本都会使用到微信好友或者微信朋友圈分享功能吧,那么今天我就带大家实现以下RN微信好友以及朋 ...

  2. Vue+iview实现添加删除类

    <style> .tab-warp{ border-bottom: solid 1px #e0e0e0; overflow: hidden; margin-top: 30px; posit ...

  3. 面试题(校招java)

    1:linux线程和进程的区别? 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程 ...

  4. Linux 下面RPM 安装的SQLSERVER 修改字符集的方法

    1. 自己还是太low 2. 遇到问题 先 -h 处理 3. 发现登录报错, 怀疑是字符集的问题: 4. 计划是修改字符集 到 自己的环境可用的状态 使用命令 /opt/mssql/bin/mssql ...

  5. Spring的Bean配置

    IOC和DI 网上概念很多,感兴趣可以去搜一搜,在这里我就给个比喻: IOC:以前我们买东西都要去商店买,用了IOC之后,我们只要在门口放个箱子, Spring就会给我相应商品,ಠᴗಠ 举个例子 cl ...

  6. Dom4j解析

    dom4j-1.6.1.jar, 这个包提供了xml解析相关的方法. 这里做一个记录,微信公众号里需要对HttpServletRequest做解析,实际上也可以用dom4j提供的方法进行解析转换. 这 ...

  7. Appscanner实验还原code3

    # Author: Baozi #-*- codeing:utf-8 -*- import _pickle as pickle from sklearn import ensemble import ...

  8. Window下通过SecureCRT的SSH2跳转到另一台Linux服务器

    我工作中的示例: 先登录192.168.2.145 Your password will be expired in 200 days.Welcome to Baoleiji System.Last ...

  9. k8s使用glusterfs做存储

    一.安装glusterfs https://www.cnblogs.com/zhangb8042/p/7801181.html 环境介绍; centos 7 [root@k8s-m ~]# cat / ...

  10. 老男孩python学习自修第八天【函数式编程】

    1.可变参数,将传参自动汇总成列表 2.可变参数,将参数自动汇总成字典 实战如下: #!/usr/bin/env python # _*_ coding:UTF-8 _*_ def show(*arg ...