原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4573

大森林

Description

小Y家里有一个大森林,里面有n棵树,编号从1到n。一开始这些树都只是树苗,只有一个节点,标号为1。这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力。小Y掌握了一种魔法,能让第l棵树到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?

Input

第一行包含 2 个正整数 n,m,共有 n 棵树和 m 个操作。接下来 m 行,每行包含若干非负整数表示一个操作,操作格式为:

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 存在。N<=105,M<=2*105

Output

输出包括若干行,按顺序对于每个小Y的询问输出答案

Sample Input

5 5
0 1 5
1 2 4 2
0 1 4
2 1 1 3
2 2 1 3

Sample Output

1
2

题解

做法当然是大力LCT然后乖乖TLE

首先,很显然的是,询问中每棵树都是独立的,互不干扰,再加上题目中同一次000操作生成的节点编号是一样的,一起操作非常麻烦,我们不如一棵树一棵树的处理操作。因此,我们考虑将操作离线下来,从左向右处理对于每棵树的询问。

那么如何处理每个操作呢?

那么我们到底离线了些啥,怎么离线??

观察所有的操作,如果没有111操作,那么所有点都长到一起,随便乱接都无所谓。类比一下,没有改变生长点的时候,由于是长到同一个节点上,而我们的询问是针对两点间路径的,所以一棵树上即使长了不属于自己的节点也不会影响答案。所以针对每次更改生长点的操作,我们建立一个虚节点;生长节点时,建立一个实节点,连接到最近生成的虚节点上,我们将所有虚节点按时间顺序串起来。

考虑我们处理操作的过程:先把所有节点长好,再处理生长节点的修改和询问。

那么111操作到底改了什么呢?对于一个形如1lerix1\ le\ ri\ x1 le ri x的操作,我们新建了一个虚点。虚点的有效区间为le→rile\to rile→ri,当我们处理到lelele时,把对应的子树切下来,接到对应的实节点上,统计答案;到ri+1ri+1ri+1时再把那个子树切下来接回原来的虚点上。

对于子树嫁接这个操作LCT\mathcal{LCT}LCT直接搞有点麻烦(会ETTETTETT的大佬请坐下),为此,我们引入一些“虚点”,把节点都连到虚点上,嫁接时直接把虚点连过去。因为要统计路径长度,我们把虚点的权值设为000,实点权值为111,维护一下子树大小即可。

值得一提的是,当统计路径长度的时候我们不能直接split(x,y)\mathcal{split(x,y)}split(x,y),因为原来的树为有根树,而makeroot\mathcal{makeroot}makeroot的时候因为有区间反转之类的操作,会破坏原来的父子关系;另外,两个节点的LCA\mathcal{LCA}LCA有可能是虚点,它们真正的LCA\mathcal{LCA}LCA是该虚点的某个祖先,所以是不行的。但是我们可以借用树上差分的思路,借助LCA\mathcal{LCA}LCA来解决这个问题:
ans=siz[x]+siz[y]−2×siz[LCAx,y]ans=siz[x]+siz[y]-2\times siz[LCA_{x,y}]ans=siz[x]+siz[y]−2×siz[LCAx,y​]

那么如何求LCT\mathcal{LCT}LCT上的LCA\mathcal{LCA}LCA呢?

我们先access(x),splay(x)\mathcal{access(x)},splay(x)access(x),splay(x),再access(y)access(y)access(y),在access(y)access(y)access(y)的过程中最后跳到的虚边对应节点就是x,yx,yx,y的LCA\mathcal{LCA}LCA,简单的图示:

access(x):

splay(x):

access(y):


值得注意的是,上述性质也是得益于没有换根才有的。

代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
using namespace std;
const int M=1e6+5;
struct sd{int pos,op,x,y;};
bool operator <(sd a,sd b){return a.pos==b.pos?a.op<b.op:a.pos<b.pos;}
int dad[M],son[M][2],siz[M],ans[M],tot,last,id[M],idd,top,le[M],ri[M],qs,n,m;
bool r[M];sd que[M];
bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
void up(int v){siz[v]=siz[ls]+siz[rs]+r[v];}
void spin(int v)
{int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];if(notroot(f))son[ff][son[ff][1]==f]=v;son[v][!k]=f;son[f][k]=w;if(w)dad[w]=f;dad[f]=v;dad[v]=ff;up(f);up(v);
}
void splay(int v)
{int f,ff;while(notroot(v)){f=dad[v];ff=dad[f];if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);spin(v);}
}
int access(int v){int f=0;for(;v;v=dad[f=v])splay(v),rs=f,up(v);return f;}
void link(int x,int y){splay(x);dad[x]=y;}
void cut(int v){access(v);splay(v);dad[ls]=0;ls=0;up(v);}
int query(int x,int y)
{int ans=0,t;access(x);splay(x);ans+=siz[x];t=access(y);splay(y);ans+=siz[y];access(t);splay(t);ans-=2*siz[t];return ans;
}
void _new(int x){r[++tot]=x;siz[tot]=x;}
void in()
{scanf("%d%d",&n,&m);_new(1);idd=1;le[1]=1;ri[1]=n;id[1]=1;_new(0);last=2;link(2,1);int op,a,b,c,l,r;for(int i=1;i<=m;++i){scanf("%d%d%d",&op,&a,&b);switch(op){case 0:_new(1);le[++idd]=a;ri[idd]=b;id[idd]=tot;que[++top]=(sd){1,i-m,tot,last};break;case 1:{scanf("%d",&c);a=max(a,le[c]);b=min(b,ri[c]);if(a<=b){_new(0);link(tot,last);que[++top]=(sd){a,i-m,tot,id[c]};que[++top]=(sd){b+1,i-m,tot,last};last=tot;}break;}case 2:scanf("%d",&c);que[++top]=(sd){a,++qs,id[b],id[c]};}}
}
void ac()
{sort(que+1,que+1+top);for(int i=1,j=1;i<=n;++i){for(;j<=top&&que[j].pos==i;++j)if(que[j].op<=0)cut(que[j].x),link(que[j].x,que[j].y);else ans[que[j].op]=query(que[j].x,que[j].y);}for(int i=1;i<=qs;++i)printf("%d\n",ans[i]);
}
int main()
{in();ac();return 0;
}

BZOJ4573[ZJOI2016] 大森林相关推荐

  1. [BZOJ4573][[Zjoi2016]大森林][LCT建虚点]

    [BZOJ4573][[Zjoi2016]大森林][LCT建虚点] 题意懒得写了.... 思路: 建LCT的时候我们可以引入虚点.对于所有的1操作,新建一个没有权值的虚点,然后对于0操作,可以把新建的 ...

  2. [2019.3.20]BZOJ4573 [Zjoi2016]大森林

    发现一个重要的性质:由于不存在删点的操作,所以之后的加点并不会对之前的询问的答案造成影响. 所以我们可以先处理修改,再处理询问. 考虑从左到右扫描每一颗树,每次将前一棵树通过一些修改变为后一棵树. 发 ...

  3. BZOJ4573 : [Zjoi2016]大森林

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

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

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

  5. bzoj 4573: [Zjoi2016]大森林

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

  6. [ZJOI2016]大森林

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

  7. [ZJOI2016]大森林(LCT)

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

  8. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  9. 3825. 逃离大森林

    3825. 逃离大森林 题目链接 #include <bits/stdc++.h> #define x first #define y second using namespace std ...

  10. CF_329_B----AcWing_3825_逃离大森林(BFS究极模板)

    原题链接:https://www.acwing.com/problem/content/3828/ 你是一个宝可梦饲养员,你正在进行你的冒险之旅. 当前,你的目标是逃离飞鸟森林. 飞鸟森林可以表示为一 ...

最新文章

  1. 2020 腾讯广告算法大赛:突破高分瓶颈方案分享
  2. Cant find model en_core_web_sm
  3. 7月11日任务 shell介绍、shell结构和执行 、date命令用法、shell脚本中的变量
  4. 基于 Jenkins 快速搭建持续集成环境--转
  5. 熟悉Java String的使用,熟悉String的各种函数,Java中各种变量类型
  6. Ubuntu21.04开机自动挂载Windows硬盘分区
  7. Kotlin实战指南十九:use 函数魔法
  8. JavaScript原生对象属性和方法详解——String对象
  9. 异常注意事项_多异常的捕获处理
  10. Java基础之参数传递
  11. 光伏产业的发展推动太阳能组件技术进步
  12. mybatis生成工具
  13. Java中condition的用法_java5 Condition用法--实现线程间的通信
  14. 大学生python心得1000字_大学生读书心得1000字3篇
  15. 计算机键盘如何打字课件,电脑键盘打字入门基础.ppt
  16. Google登陆集成笔记-含坑
  17. 特殊字符是哪些字符python_python特殊字符
  18. vue中头像加载不出来,怎样设置默认头像
  19. 当我说要做大数据工程师时他们都笑我,直到三个月后……
  20. logo怎么设计才好看?好看的logo设计方法大公开。

热门文章

  1. 网站子域名扫描程序,采用三种扫描方式(crt网站查询、站长网站查询、字典暴力破解)
  2. 简述Java面向对象的基本思想_Java面向对象的基本思想理解
  3. 浮窗 动画特效 android,悬浮窗能实现自定Animation动画效果吗?
  4. LeetCode--Longest Common Prefix
  5. 新浪微博客户端(33)-显示头像上的认证类型
  6. Java的redis控制台-Jedis
  7. 早该知道的7个JavaScript技巧
  8. (转) Lua使用心得一
  9. java日志分级概要
  10. javascript中对象的深度克隆