Description:

小Y家里有一个大森林,里面有n棵树,编号从1到n

0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例如,第一个 0 号操作产生的子节点标号为 2), l 到 r 之间的树长出的节点标号都相同。保证 1<=l<=r<=n 。

1 l r x 表示将第 l 棵树到第 r 棵树的生长节点改到标号为 x 的节点。对于 i (l<=i<=r)这棵树,如果标号 x的点不在其中,那么这个操作对该树不产生影响。保证 1<=l<=r<=n , x 不超过当前所有树中节点最大的标号。

2 x u v 询问第 x 棵树中节点 u 到节点 v 点的距离,也就是在第 x 棵树中从节点 u 和节点 v 的最短路上边的数量。保证1<=x<=n,这棵树中节点 u 和节点 v 存在。

Hint:

$ N<=105,M<=2*105 $

Solution:

一开始想到线段树套LCT,然而标记无法下传

考虑朴素做法,每个节点用LCT维护一片森林,空间显然无法承受

这时我们需要转换思路

因为题目没有强制在线,所以我们可以只维护一颗”树“,然后按顺序处理1、2操作

每次1操作直接把该生长节点的子树”嫁接“到另一个生长节点

为了保证复杂度,我们需要在生长节点处开一个虚点,这样就不需要多点换父亲了

2操作直接用求个LCA就行了

#include<bits/stdc++.h>
using namespace std;
const int mxn=3e5+5;
struct Q {
int pos,id,x,y,qr;
}q[mxn];
int n,m,p,s,tot,cnt,sum;
int t[mxn],lp[mxn],rp[mxn],bl[mxn],fa[mxn],ch[mxn][2],ans[mxn],val[mxn]; int cmp(Q x,Q y) {
return x.pos==y.pos?x.id<y.id:x.pos<y.pos;
} namespace lct {
int isnotrt(int x) {
return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
}
void push_up(int x) {
t[x]=t[ch[x][0]]+t[ch[x][1]]+val[x];
}
void rotate(int x) {
int y=fa[x],z=fa[y],tp=ch[y][1]==x;
if(isnotrt(y)) ch[z][ch[z][1]==y]=x; fa[x]=z;
ch[y][tp]=ch[x][tp^1]; fa[ch[x][tp^1]]=y;
ch[x][tp^1]=y; fa[y]=x;
push_up(y),push_up(x);
}
void splay(int x) {
while(isnotrt(x)) {
int y=fa[x],z=fa[y];
if(isnotrt(y))
(ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
rotate(x);
}
}
int access(int x) {
int y;
for(y=0;x;x=fa[y=x])
splay(x),ch[x][1]=y,push_up(x);
return y;
}
void link(int x,int y) {
splay(x); fa[x]=y;
}
void cut(int x) {
access(x); splay(x);
ch[x][0]=fa[ch[x][0]]=0;
push_up(x);
}
}
using namespace lct; int main()
{
scanf("%d%d",&n,&m); int res,lca,opt,l,r,x,y;
p=tot=val[1]=t[1]=lp[1]=bl[1]=1; rp[1]=n; int now=2; link(++p,1);
for(int i=1;i<=m;++i) {
scanf("%d",&opt);
if(opt==0) {
scanf("%d%d",&l,&r);
bl[++tot]=++p; link(p,now); //每次把新节点直接长在最近更新的生成节点,考虑这样为什么不会错,因为实点之间的虚点不会影响答案
lp[tot]=l,rp[tot]=r;
val[p]=t[p]=1;
}
else if(opt==1) {
scanf("%d%d%d",&l,&r,&x);
l=max(l,lp[x]); r=min(r,rp[x]);
if(l>r) continue;//去掉无用的区间
link(++p,now);
q[++s]=(Q){l,i,p,bl[x],0};
q[++s]=(Q){r+1,i,p,now,0};
now=p;
}
else scanf("%d%d%d",&l,&x,&y),q[++s]=(Q){l,i,bl[x],bl[y],++sum};
}
sort(q+1,q+s+1,cmp);
for(int i=1;i<=s;++i) {
if(q[i].qr>0) {
access(q[i].x); splay(q[i].x); res=t[q[i].x]; //因为这题规定根为1,所以我们不能makert
lca=access(q[i].y); splay(q[i].y); res+=t[q[i].y];
access(lca); ans[q[i].ss]=res-t[lca]*2;
}
else cut(q[i].x),link(q[i].x,q[i].y);
}
for(int i=1;i<=sum;++i) printf("%d\n",ans[i]);
return 0;
}

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

  1. [ZJOI2016]大森林(LCT)

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

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

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

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

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

  4. bzoj 4573: [Zjoi2016]大森林

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

  5. P3348 [ZJOI2016]大森林

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

  6. 【LuoguP3348】[ZJOI2016]大森林

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

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

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

  8. BZOJ4573 : [Zjoi2016]大森林

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

  9. ●洛谷P3348 [ZJOI2016]大森林

    题链: https://www.luogu.org/problemnew/show/P3348 题解: LCT,神题 首先有这么一个结论: 每次的1操作(改变生长点操作),一定只会会对连续的一段区间产 ...

随机推荐

  1. Html页面添加百度地图

    1.进入百度地图开放平台 http://lbsyun.baidu.com/ 2.进入右上角的   “API控制台” 在这里创建应用 并 获取密钥 3.进入 如下地址 创建地图 http://api.m ...

  2. 饮冰三年-人工智能-linux-02 初始Linux

    参考博客:https://www.cnblogs.com/linhaifeng/articles/6045600.html 1:初始Linux命令 右击,开启终端,或者ctrl+alt[F1-F6]的 ...

  3. What is base..ctor(); in C#?

    I am disassembling some C# applications and I am trying to reconstruct the source code. I am disasse ...

  4. 企业级代码托管Gitlab

    Gitlab概述: 一个利用Ruby on Rails开发的开元应用程序,从而实现一个代码托管项目仓库,可以通过web界面进行访问公开的或者私有的项目 Ruby on Rails是一个可以使开发,部署 ...

  5. Codeforces 1137D Cooperative Game (看题解)

    Cooperative Game 智商题, 感觉不太能推出来, 虽然看看证明过程是对的. #include<bits/stdc++.h> #define LL long long #def ...

  6. 2018牛客网暑假ACM多校训练赛(第四场)C Chiaki Sequence Reloaded (组合+计数) 或 数位dp

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round4-C.html 题目传送门 - https://www.no ...

  7. .bat批处理添加Python任务

    一.常用命令含义 例一.多进程python 任务  --  start 命令 @echo offstart python C:\Users\ntitled\n\update_restt\test_ba ...

  8. Number Sequence kmp

    Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], .... ...

  9. 048 SparkSQL自定义UDAF函数

    一:程序 1.需求 实现一个求平均值的UDAF. 这里保留Double格式化,在完成求平均值后与系统的AVG进行对比,观察正确性. 2.SparkSQLUDFDemo程序 package com.sc ...

  10. Python GUI - tkinter

    目录: Tkinter 组件 标准属性 几何管理 代码实例: 1. Label & Button 2. Entry & Text 3.Listbox列表 4.Radiobutton单选 ...