Description

小Y家里有一个大森林,里面有n棵树,编号从1到n。一开始这些树都只是树苗,只有一个节点,标号为1。这些树

都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力。小Y掌握了一种魔法,能让第l棵树

到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的

记录,你能不能管理她家的森林,并且回答她的询问呢?

Solution

有点神仙,看了题解的做法

首先显然要离线,否则空间都是错的,这样维护一棵树就好了

然后发现都是区间修改,扫描线维护一下节点就好了

但是还有删除节点这样的操作,复杂度保证不了

不如先把树的形态都建出来,对于 \(1\) 到 \(n\) 的公共部分我们一起考虑,不同的部分就直接新建节点

考虑维护添加,删除操作的复杂度

我们每产生一个新的生长节点就新建一个虚点,然后把新长出来的都接上去

如果按加入时间考虑的话,有很多连续的节点都是同一个父亲,所以我们用一个虚点暂时代替它们的父亲

然后对于 \(1\) 到 \(n\) 的不同的树,它们的父亲是不一样的,因为建立了这个虚点,所以只需要把虚点的父亲变一下,就可以达到把所有的点的父亲都改变的效果了

具体的也说不清楚,看代码比较直观.....

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. template<class T>void gi(T &x){
  4. int f;char c;
  5. for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
  6. for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
  7. }
  8. const int N=4e5+10;
  9. int n,m,ch[N][2],fa[N],a[N],w[N];
  10. inline void upd(int x){w[x]=w[ch[x][0]]+w[ch[x][1]]+a[x];}
  11. inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
  12. inline void rotate(int x){
  13. int y=fa[x];bool t=ch[y][1]==x;
  14. ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
  15. ch[x][!t]=y;fa[x]=fa[y];
  16. if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
  17. fa[y]=x;upd(y);upd(x);
  18. }
  19. inline void splay(int x){
  20. while(!isrt(x)){
  21. int y=fa[x],p=fa[y];
  22. if(isrt(y))rotate(x);
  23. else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
  24. else rotate(x),rotate(x);
  25. }
  26. }
  27. inline int access(int x){
  28. int y=0;
  29. while(x)splay(x),ch[x][1]=y,upd(x),x=fa[y=x];
  30. return y;
  31. }
  32. inline void link(int x,int y){
  33. access(x);splay(x);fa[x]=y;
  34. }
  35. inline void cut(int x){
  36. access(x);splay(x);fa[ch[x][0]]=0;ch[x][0]=0;upd(x);
  37. }
  38. inline int query(int x,int y){
  39. int ret=0,t;
  40. access(x);splay(x);ret+=w[x];
  41. t=access(y);splay(y);ret+=w[y];
  42. access(t);splay(t);ret-=w[t]<<1;
  43. return ret;
  44. }
  45. int L[N],R[N],id[N],cnt=2,ans[N],top=0;
  46. struct data{
  47. int ty,p,x,y;
  48. inline bool operator <(const data &t)const{
  49. if(p!=t.p)return p<t.p;
  50. return ty<t.ty;
  51. }
  52. }q[N];
  53. int main(){
  54. freopen("pp.in","r",stdin);
  55. freopen("pp.out","w",stdout);
  56. cin>>n>>m;
  57. int op,l,r,x,y=2,tp=0,ID=1;
  58. L[1]=1;R[1]=n;id[1]=1;w[1]=a[1]=1;
  59. L[2]=1;R[2]=n;w[2]=a[2]=0;link(2,1);
  60. for(int i=1;i<=m;i++){
  61. gi(op);gi(l);gi(r);
  62. if(op==0){
  63. a[++cnt]=1;w[cnt]=1;L[++ID]=l;R[ID]=r;id[ID]=cnt;
  64. link(cnt,y);
  65. }
  66. else if(op==1){
  67. gi(x);
  68. a[++cnt]=0;w[cnt]=0;l=max(l,L[x]);r=min(r,R[x]);
  69. if(l<=r){
  70. link(cnt,y);
  71. q[++top]=(data){-1,l,cnt,id[x]};
  72. q[++top]=(data){-1,r+1,cnt,y};
  73. y=cnt;
  74. }
  75. }
  76. else gi(x),q[++top]=(data){++tp,l,id[r],id[x]};
  77. }
  78. sort(q+1,q+top+1);
  79. for(int i=1,j=1;i<=n;i++){
  80. while(j<=top && q[j].p==i){
  81. if(q[j].ty==-1)cut(q[j].x),link(q[j].x,q[j].y);
  82. else ans[q[j].ty]=query(q[j].x,q[j].y);
  83. j++;
  84. }
  85. }
  86. for(int i=1;i<=tp;i++)printf("%d\n",ans[i]);
  87. return 0;
  88. }

bzoj 4573: [Zjoi2016]大森林的更多相关文章

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

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

  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. BZOJ4573:[ZJOI2016]大森林——题解

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

  4. [ZJOI2016]大森林(LCT)

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

  5. [ZJOI2016]大森林

    Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 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]大♂森林

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

随机推荐

  1. 如何将Sql server数据库中的模型图转化到Word中--并能够查看字段的属性信息

    1. 在Sql server数据库中创建数据库的模型图 -- Database Diagrams 2. 控制面板--管理工具--ODBC数据源链接--创建一个Sql server的数据源链接 3. 打 ...

  2. 使用django进行发送 邮件

    我们来看一下 django发送 邮件的整个流程 第一步:例先去 网易163注册账号并激活发邮件功能 把授权码进行 开启 来到我们的项目setting中进行 一个配置: # 邮箱的配置信息 EMAIL_ ...

  3. luoguP4782 [模板]2-SAT问题

    https://www.luogu.org/problemnew/show/P4782 2-SAT模板,输出方案只需判断 \(a\) 和 \(a + n\) 两个点所在的 scc 编号大小就可以了 # ...

  4. 1.线性回归、Logistic回归、Softmax回归

    本次回归章节的思维导图版总结已经总结完毕,但自我感觉不甚理想.不知道是模型太简单还是由于自己本身的原因,总结出来的东西感觉很少,好像知识点都覆盖上了,但乍一看,好像又什么都没有.不管怎样,算是一次尝试 ...

  5. Servlet的概念与用法

    Servlet: Servlet(Servlet+Applet) Servlet是一种独立于平台和协议的服务器端Java应用程序,通用Servlet      可以生成动态Web页面.Servlet还 ...

  6. Unity---动画系统学习(3)---使用状态机来实现走、跑、转弯等的动画切换

    1. 初始设置 用动画学习笔记(2)中方法,把动画全都切割好. 拖进状态机并设置箭头.并设置具体箭头触发的事件. 在状态机左侧中添加参数,Float和Int类型参数只能从-1~1之间变化 Float: ...

  7. JavaScript 跨域总结与解决办法

    什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首 ...

  8. ubuntu下的pycharm4中文路径乱码

    修改字体: 设置(settings)->外观与行为(appearance & behavior) -> 外观(appearance) ->我选择的主题是Darcula 但其字 ...

  9. C# 委托的三种调用示例(同步调用、异步调用、异步回调)

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...

  10. 什么是LINQ

    LINQ 什么是LINQLINQ提供程序 匿名类型 方法语法和查询语法查询变量查询表达式的结构 from子句join子句什么是联结查询主体中的from…let…where片段 from子句let子句w ...