题目描述

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

小Y掌握了一种魔法,能让第 $l$ 棵树到第 $r$ 棵树的生长节点长出一个子节点。同时她还能修改第 $l$ 棵树到第 $r$ 棵树的生长节点。

她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?

输入格式

第一行包含 2 个正整数 $n,m$,共有 $n$ 棵树和 $m$ 个操作。

接下来 $m$ 行,每行包含若干非负整数表示一个操作,操作格式为:

  1. $0$ $l$ $r$ 表示将第 $l$ 棵树到第 $r$ 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 $0$ 号操作叶子标号加 $1$(例如,第一个 $0$ 号操作产生的子节点标号为 $2$),$l$ 到 $r$ 之间的树长出的节点标号都相同。保证 $1\leq l \leq r \leq n$。
  2. $1$ $l$ $r$ $x$ 表示将第 $l$ 棵树到第 $r$ 棵树的生长节点改到标号为 $x$ 的节点。对于区间内的每棵树,如果标号 $x$ 的点不在其中,那么这个操作对该树不产生影响。保证 $1 \leq l \leq r \leq n$,$x$ 不超过当前所有树中节点最大的标号。
  3. $2$ $x$ $u$ $v$ 询问第 $x$ 棵树中节点 $u$ 到节点 $v$ 的距离,也就是在第 $x$ 棵树中从节点 $u$ 和节点 $v$ 的最短路上边的数量。保证 $1 \leq x \leq n$,这棵树中节点 $u$ 和节点 $v$ 存在。

输出格式

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

限制与约定

测试点编号 $n$ $m$ 约定
1 $\leq 10^3$ $\leq 10^3$
2 $\leq 10^5$ $\leq 2 \times 10^5$ 保证每次 $0$ 和 $1$ 操作修改的是 $1$ 到 $n$ 所有的树
3
4 保证每次 $0$ 操作生长节点都是这些树中编号最大的节点
5
6
7
8
9
10

时间限制:$2\texttt{s}$

空间限制:$256\texttt{MB}$


据说这道题目是cls出的....部分分还是给的很良心的


分析1

第一部分数据,直接暴力dfs,随便搞10分

第二部分数据,写一个LCA即可,20分

第三部分数据,由于生长点都是最大点,那么只需要线段树维护,由于有\(n\)棵线段树,直接主席树搞一搞就好了

这三部分似乎都是纯模板啊?直接可以获得50分

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<string>
  5. #include<cmath>
  6. #include<climits>
  7. #include<cstdlib>
  8. #include<vector>
  9. #include<algorithm>
  10. #include<queue>
  11. #include<stack>
  12. #include<map>
  13. #define ll long long
  14. using namespace std;
  15. inline char nc(){
  16. static char buf[100000],*p1=buf,*p2=buf;
  17. if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  18. return *p1++;
  19. }
  20. inline void read(int &x){
  21. char c=nc(),b=1;
  22. for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  23. for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
  24. }
  25. inline void read(ll &x){
  26. char c=nc(),b=1;
  27. for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  28. for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
  29. }
  30. int wt,ss[19];
  31. inline void print(int x){
  32. if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
  33. }
  34. inline void print(ll x){
  35. if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
  36. }
  37. int n,m;
  38. int Grow[100010],D[1010][1010],FA[1010][1010],c[10010];
  39. struct data
  40. {
  41. int t,x,y,z;
  42. }Work[200010];
  43. int S,d[200010],p[400010][20];
  44. int root[300010],tot;
  45. int Ls[300010*30],Rs[300010*30],add[300010*30];
  46. ll sum[300010*30];
  47. inline int bulidtree(int L,int R){
  48. int k=tot++;
  49. add[k]=0;
  50. if (L==R){
  51. scanf("%lld",&sum[k]);
  52. return k;
  53. }
  54. int mid=(L+R)>>1;
  55. Ls[k]=bulidtree(L,mid);
  56. Rs[k]=bulidtree(mid+1,R);
  57. sum[k]=sum[Ls[k]]+sum[Rs[k]];
  58. return k;
  59. }
  60. inline int update(int o,int L,int R,int x,int LL,int RR){
  61. int k=tot++;
  62. Ls[k]=Ls[o]; Rs[k]=Rs[o]; add[k]=add[o]; sum[k]=sum[o];
  63. sum[k]+=(ll)x*(R-L+1);
  64. if (LL==L && RR==R){
  65. add[k]+=x;
  66. return k;
  67. }
  68. int mid=(LL+RR)>>1;
  69. if (R<=mid) Ls[k]=update(Ls[k],L,R,x,LL,mid);
  70. else if (L>mid) Rs[k]=update(Rs[k],L,R,x,mid+1,RR);
  71. else {
  72. Ls[k]=update(Ls[k],L,mid,x,LL,mid);
  73. Rs[k]=update(Rs[k],mid+1,R,x,mid+1,RR);
  74. }
  75. return k;
  76. }
  77. inline ll query(int o,int L,int R,int LL,int RR){
  78. if (L==LL && R==RR) return sum[o];
  79. int mid=(LL+RR)>>1;
  80. ll ret=(ll)add[o]*(R-L+1);
  81. if (R<=mid) return ret+query(Ls[o],L,R,LL,mid);
  82. else if (L>mid) return ret+query(Rs[o],L,R,mid+1,RR);
  83. else return ret+query(Ls[o],L,mid,LL,mid)+query(Rs[o],mid+1,R,mid+1,RR);
  84. }
  85. int lca(int x,int y)
  86. {
  87. if (d[x]<d[y]) swap(x,y);
  88. int i;
  89. for (i=0;(1<<i)<=d[x];i++);i--;
  90. for (int j=i;j>=0;j--)
  91. if (d[x]-(1<<j)>=d[y]) x=p[x][j];
  92. if (x==y) return x;
  93. for (int j=i;j>=0;j--)
  94. if (p[x][j]!=-1 && p[x][j]!=p[y][j])
  95. x=p[x][j],y=p[y][j];
  96. return p[x][0];
  97. }
  98. int main()
  99. {
  100. read(n);read(m);
  101. if (n<=1000 && m<=1000)
  102. {
  103. int s=1;
  104. for (int i=1;i<=n;i++)
  105. Grow[i]=1,D[i][1]=1;
  106. int x,y,z;
  107. while (m--)
  108. {
  109. read(x);
  110. if (x==0)
  111. {
  112. read(x);read(y);
  113. s++;
  114. for (int i=x;i<=y;i++)
  115. FA[i][s]=Grow[i],D[i][s]=D[i][Grow[i]]+1;
  116. }
  117. else if (x==1)
  118. {
  119. read(x);read(y);read(z);
  120. for (int i=x;i<=y;i++)
  121. if (D[i][z]>0) Grow[i]=z;
  122. }
  123. else if (x==2)
  124. {
  125. read(x);read(y);read(z);
  126. int t=D[x][y]+D[x][z];
  127. while (D[x][y]>D[x][z]) y=FA[x][y];
  128. while (D[x][z]>D[x][y]) z=FA[x][z];
  129. while (y!=z) y=FA[x][y],z=FA[x][z];
  130. print(t-2*D[x][y]),putchar('\n');
  131. }
  132. }
  133. return 0;
  134. }
  135. int flag=0,s=1,t=1;
  136. for (int i=1;i<=m;i++)
  137. {
  138. read(Work[i].t);
  139. if (Work[i].t==0 || Work[i].t==1)
  140. {
  141. read(Work[i].x);read(Work[i].y);
  142. if (Work[i].x!=1 || Work[i].y!=n) flag=1;
  143. if (Work[i].t==1) read(Work[i].z);
  144. }
  145. else read(Work[i].x),read(Work[i].y),read(Work[i].z);
  146. }
  147. if (!flag)
  148. {
  149. int s=1,grow=1;
  150. d[1]=1;
  151. for (int i=1;i<=m;i++)
  152. {
  153. if (Work[i].t==0)
  154. {
  155. s++;
  156. d[s]=d[grow]+1;
  157. p[s][0]=grow;
  158. for (int j=1;(1<<j)<=s;j++)
  159. if (p[s][j-1]!=-1) p[s][j]=p[p[s][j-1]][j-1];
  160. }
  161. else if (Work[i].t==1) grow=Work[i].z;
  162. else
  163. {
  164. int x=Work[i].y,y=Work[i].z,z=lca(x,y);
  165. print(d[x]+d[y]-2*d[z]),putchar('\n');
  166. }
  167. }
  168. }
  169. else
  170. {
  171. tot=0;
  172. root[0]=bulidtree(1,n);
  173. int now=1;
  174. for (int i=1;i<=m;i++)
  175. if (Work[i].t==0)
  176. {
  177. now++;
  178. root[now]=update(root[now-1],Work[i].x,Work[i].y,1,1,n);
  179. }
  180. else if (Work[i].t==2)
  181. {
  182. print(abs(query(root[Work[i].z],Work[i].x,Work[i].x,1,n)-query(root[Work[i].y],Work[i].x,Work[i].x,1,n))),putchar('\n');
  183. }
  184. }
  185. return 0;
  186. }

【ZJOI2016】大♂森林的更多相关文章

  1. [ZJOI2016]大森林(LCT)

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

  2. [ZJOI2016]大森林

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

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

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

  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. P3348 [ZJOI2016]大森林

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

  7. 【LuoguP3348】[ZJOI2016]大森林

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

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

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

  9. BZOJ4573 : [Zjoi2016]大森林

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

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

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

随机推荐

  1. python3.6:DLL load failed:找不到指定的模块(from PyQt5 import QtCore)

    本人小白搭建pyqt环境时遇到问题 运行代码 from PyQt5 import QtCore' 发现错误 ImportError: DLL load failed: 找不到指定的模块 这个问题折磨了 ...

  2. Restful API 概念解析

    什么是restful? REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”. ...

  3. python数据类型之字典(dict)和其常用方法

    字典的特征: key-value结构key必须可hash,且必须为不可变数据类型.必须唯一. # hash值都是数字,可以用类似于2分法(但比2分法厉害的多的方法)找.可存放任意多个值.可修改.可以不 ...

  4. Party Games UVA - 1610 贪心

    题目:题目链接 思路:排序后处理到第一个不同的字符,贪心一下就可以了 AC代码: #include <iostream> #include <cstdio> #include ...

  5. Linux学习-Linux 主机上的用户讯息传递

    查询使用者: w, who, last, lastlog 如果你想要知道目前已登入在系统上面的用户呢?可以透过 w 或 who 来查询喔!如下范例所示: [root@study ~]# w 01:49 ...

  6. Mysql显示某个数据库的所有表

    显示表名: show tables; //先用use进入要查看表的库 mysql> use mysql; Database changed mysql> show tables; +--- ...

  7. HDU 4871 Shortest-path tree 最短路 + 树分治

    题意: 输入一个带权的无向连通图 定义以顶点\(u\)为根的最短路生成树为: 树上任何点\(v\)到\(u\)的距离都是原图最短的,如果有多条最短路,取字典序最小的那条. 然后询问生成树上恰好包含\( ...

  8. 转:Generating PDFs from Web Pages on the Fly with jsPDF

    The Portable Document Format has been one the major innovations in the fields of desktop publishing ...

  9. 01_Java 软、弱引用语法介绍

    文章导读: 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用, 本章内容介绍了Reference的概 ...

  10. 设计模式之单例模式 Singleton

    核心作用 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. 常见应用场景 优点 由于单例模式只生成一个实例,减少了系统性开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他依赖对 ...