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

https://www.luogu.org/problemnew/show/P3348#sub

http://uoj.ac/problem/195

https://loj.ac/problem/2092

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

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

参考:http://www.sigongzi.org/index.php/archives/LOJ2092.html

思路:

显然我们不能对每棵树LCT维护一下,而且我们对于这棵树的形态还很严格。

那么我们把前一棵树的形态转换为后一棵树的形态,这样就只需要一棵树了。

先考虑对于0操作,实际上我们可以记录每个时刻每个节点在哪一段区间中(代码的L和R就是干这个的),所以我们大可以对所有的树都进行0操作。

对于1操作,和0操作类似,用L和R更新l和r后进行操作。

然后为了能够快捷的更新树,我们建立一个size为0的虚点(这样对于路径长度就不需要修改了),所有的生长操作都在上面进行,这样我们删除的时候cut这个点即可。

对于2操作,事实上两个点一定存在的话,完全可以让0和1操作全部排到它的前面。

实现:

先把所有操作存下来,然后以操作的树为第一关键字,操作编号和顺序为第二关键字排序。

(对于区间修改思考差分,毕竟我们都是对同一棵树操作的。)

然后按树编号从左到右进行操作,对于0和1操作先对虚点清空然后长即可。

查询的时候就是用LCA求最短路的方法一样。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
const int N=4e5+;
struct data{
int pos,id,from,to;
}qry[N];
int n,m,fa[N],tr[N][],val[N],size[N];
int cnt,tot,sum,aux,L[N],R[N],id[N],ans[N];
inline bool cmp(data a,data b){
return a.pos<b.pos||(a.pos==b.pos&&a.id<b.id);
}
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
inline bool get(int x){
return tr[fa[x]][]==x;
}
inline bool isroot(int x){
if(!fa[x])return ;
return tr[fa[x]][]!=x&&tr[fa[x]][]!=x;
}
inline void upt(int x){
size[x]=val[x];
if(tr[x][])size[x]+=size[tr[x][]];
if(tr[x][])size[x]+=size[tr[x][]];
}
inline void rotate(int x){
int y=fa[x],z=fa[y],b=tr[y][]==x?tr[x][]:tr[x][];
if(z&&!isroot(y))(tr[z][]==y?tr[z][]:tr[z][])=x;
fa[x]=z;fa[y]=x;b?fa[b]=y:;
if(tr[y][]==x)tr[x][]=y,tr[y][]=b;
else tr[x][]=y,tr[y][]=b;
upt(y);upt(x);
}
inline void splay(int x){
while(!isroot(x)){
if(!isroot(fa[x]))
rotate((get(x)==get(fa[x])?fa[x]:x));
rotate(x);
}
upt(x);
}
inline int access(int x){
int y;
for(y=;x;y=x,x=fa[x]){
splay(x);tr[x][]=y;
if(y)fa[y]=x;
}
return y;
}
inline void link(int x,int y){
splay(y);fa[x]=y;
}
inline void cut(int x){
access(x);splay(x);
if(tr[x][])fa[tr[x][]]=;
tr[x][]=;upt(x);
}
inline void makenode(int x){
val[++sum]=x;size[sum]=x;
}
int main(){
n=read(),m=read();
cnt=;L[cnt]=,R[cnt]=n;id[cnt]=;
makenode();makenode();
aux=sum;
link(aux,id[]);
for(int i=;i<=m;i++){
int op=read();
if(op==){
L[++cnt]=read(),R[cnt]=read();
makenode();
id[cnt]=sum;
qry[++tot]=(data){,i-m,sum,aux};
}
if(op==){
int l=read(),r=read(),x=read();
l=max(l,L[x]);r=min(r,R[x]);
if(l<=r){
makenode();
link(sum,aux);
qry[++tot]=(data){l,i-m,sum,id[x]};
qry[++tot]=(data){r+,i-m,sum,aux};
aux=sum;
}
}
if(op==){
int l=read(),u=read(),v=read();
qry[++tot]=(data){l,i,id[u],id[v]};
}
}
memset(ans,-,sizeof(ans));
sort(qry+,qry+tot+,cmp);
for(int i=,p=;i<=tot;p++){
while(qry[i].pos==p){
if(qry[i].id>){
ans[qry[i].id]=;
access(qry[i].from);splay(qry[i].from);
ans[qry[i].id]+=size[qry[i].from];
int lca=access(qry[i].to);
splay(qry[i].to);
ans[qry[i].id]+=size[qry[i].to];
access(lca);splay(lca);ans[qry[i].id]-=size[lca]*;
}
else{
cut(qry[i].from);link(qry[i].from,qry[i].to);
}
i++;
}
}
for(int i=;i<=m;i++){
if(ans[i]>=)printf("%d\n",ans[i]);
}
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ4573:[ZJOI2016]大森林——题解的更多相关文章

  1. BZOJ4573 : [Zjoi2016]大森林

    扫描线,从左到右依次处理每棵树. 用set按时间顺序维护影响了这棵树的所有操作,那么一个点的父亲就是它前面第一个操作1. 用Splay维护树的括号序列,那么两点间的距离就是括号数量减去匹配的括号个数. ...

  2. [BZOJ4573][ZJOI2016]大♂森林

    bzoj luogu uoj sol \(orz\ \ HJT\ \ dalao\)教会我做这道题. 考虑每两个相邻位置的树的差异. 对于一个1操作(更换生长节点),假设区间是\([l,r]\),那么 ...

  3. [ZJOI2016]大森林(LCT)

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

  4. bzoj 4573: [Zjoi2016]大森林

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

  5. P3348 [ZJOI2016]大森林

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

  6. [ZJOI2016]大森林

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

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

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

  8. 【LuoguP3348】[ZJOI2016]大森林

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

  9. 【BZOJ4573】[ZJOI2016] 大森林(LCT)

    点此看题面 大致题意: 有\(n\)棵树,初始各有\(1\)个编号为\(1\)的节点,且其为生长节点.\(3\)种操作:将\([l,r]\)区间内的树增加一个新的编号的节点,修改\([l,r]\)区间 ...

随机推荐

  1. andriod学习一

    1.Android软件栈       2.Android模拟器        Android SDK 可以通过ADT+Eclipse或者命令行开发,调试,测试应用程序,设备可以使用模拟器或者真实设备, ...

  2. 【二】H.264/MPEG-4 Part 10 White Paper 翻译之 Prediction of Intra Macroblocks

    翻译版权所有,转载请注明出处~ xzrch@2018.09.14 ------------------------------------------------------------------- ...

  3. grep命令及正则

    文本查找 grep,egrep,fgrep grep :Global Research 根据模式搜索文本,并将符合模式的文本行显示出来 模式:Pattern,文本字符和正则的元字符组合而成匹配条件 g ...

  4. 如何编写 Python 程序

    如何编写 Python 程序 从今以后,保存和运行 Python 程序的标准步骤如下: 对于 PyCharm 用户 打开 PyCharm. 以给定的文件名创建新文件. 输入案例中给出的代码. 右键并运 ...

  5. 【label】标签组件说明

    label标签组件 用来改进表单组件的可用性,使用for属性找到对应的id,或者将控件放在该标签下,当点击时,就会触发对应的控件.目前可以绑定的控件有:<button/>, <che ...

  6. JS原型链与继承别再被问倒了

    原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...

  7. axis2调用webService几种方式

    主要有三种方式: 第一RPC方式,不生成客户端代码 第二,document方式,不生成客户端代码 第三,用wsdl2java工具,生成客户端方式调用 java代码: package samples.q ...

  8. C语言实训——扑克牌洗牌程序

    说明此程序本来是21点扑克程序的一个被调函数,在这里我单独将它拿出来作为一个小程序. #include<stdio.h> #include<time.h> #include&l ...

  9. P4语法(1)基础数据类型和Header

    文章学习自:P4语言编程详解 由于原文有一点的年份,所以也继续阅读了相关的最新规范. P4语言规范 基础数据类型 布尔型(bool) 运算符 描述 and 双目运算符,结果为布尔型 or 双目运算符, ...

  10. android 出现Make sure the Cursor is initialized correctly before accessing data from it

    Make sure the Cursor is initialized correctly before accessing data from it 详细错误是:java.lang.IllegalS ...