[ZJOI2016]大森林(LCT)
题目描述
小Y家里有一个大森林,里面有n棵树,编号从1到n。一开始这些树都只是树苗,只有一个节点,标号为1。这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力。
小Y掌握了一种魔法,能让第l棵树到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?
题解
这题太神了,废了我一下午。
看到区间操作,就可以想到差分或者扫描线,我们会发现这题基本没有好的方法去执行批量操作,所以我们要用扫描线。
这道题的操作有,区间生长一个点,区间换父亲。
我们对于每个1操作新建一个虚点,然后把它们串起来,然后把每个0操作长出来的点挂在上一个虚点上,然后一通做完之后的树长这样(白点为虚点,黑点为实点)。
时间从上到下为从早到晚。
对于一个换父亲操作,假如说我们要对最下面的白点对应的换父亲的操作换到右边从上到下第二个黑点上,那么我们可以这样。
可以手玩一下,所有有效节点对应的deep是对的。
然后我们用LCT维护这一过程,求两点
注意判断1操作的作用范围。
代码
#include<iostream> #include<cstdio> #include<algorithm> #define N 200002 using namespace std; int tr[N][2],fa[N],size[N],w[N],cnt,n,m,tot,top,b[N],L[N],R[N],ji[N],qqq,ans,ans2[N]; inline int rd(){int x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x; } inline bool isroot(int x){return !x||(tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x);} inline bool ge(int x){return tr[fa[x]][1]==x;} inline void pushup(int x){size[x]=size[tr[x][0]]+size[tr[x][1]]+w[x];} inline void newnode(int x){++cnt;w[cnt]=size[cnt]=x;} inline void rotate(int x){int y=fa[x],o=ge(x);if(isroot(x))return;tr[y][o]=tr[x][o^1];fa[tr[y][o]]=y;if(!isroot(y))tr[fa[y]][ge(y)]=x;fa[x]=fa[y];fa[y]=x;tr[x][o^1]=y;pushup(y);pushup(x); } inline void splay(int x){while(!isroot(x)){ int y=fa[x];if(isroot(y))rotate(x);else rotate(ge(y)==ge(x)?y:x),rotate(x);} } inline int access(int x){int y=0;for(;x;y=x,x=fa[x])splay(x),tr[x][1]=y,pushup(x);return y;}//qiu LCA get inline void link(int x,int y){access(x);splay(x);fa[x]=y;} inline void cut(int x){access(x);splay(x);fa[tr[x][0]]=0;tr[x][0]=0;pushup(x);} struct node{int pos,tag,x,y;inline bool operator <(const node &b)const{if(pos!=b.pos)return pos<b.pos;else return tag<b.tag;} }a[N<<1]; int main(){n=rd();m=rd();int opt,l,r,k;newnode(1);newnode(0);link(2,1);int now=2;b[tot=1]=1;L[tot]=1;R[tot]=n;for(int i=1;i<=m;++i){opt=rd();if(!opt){l=rd();r=rd();newnode(1);b[++tot]=cnt;L[tot]=l;R[tot]=r;a[++top]=node{1,i-N,cnt,now};}else if(opt==1){l=rd();r=rd();k=rd();l=max(l,L[k]);r=min(r,R[k]);if(l>r)continue;newnode(0);link(cnt,now);a[++top]=node{l,i-N,cnt,b[k]};a[++top]=node{r+1,i-N,cnt,now};now=cnt;}else{k=rd();l=rd();r=rd();ji[i]=++qqq;a[++top]=node{k,i,b[l],b[r]};}} sort(a+1,a+top+1);int p=1;for(int i=1;i<=n;++i)for(;a[p].pos==i;++p)if(a[p].tag<=0){cut(a[p].x);link(a[p].x,a[p].y);}else{ans=0;access(a[p].x);splay(a[p].x);ans+=size[a[p].x];int lca=access(a[p].y);splay(a[p].y);ans+=size[a[p].y];access(lca);splay(lca);ans-=size[lca]*2;ans2[ji[a[p].tag]]=ans;}for(int i=1;i<=qqq;++i)printf("%d\n",ans2[i]);return 0; }
转载于:https://www.cnblogs.com/ZH-comld/p/10187036.html
[ZJOI2016]大森林(LCT)相关推荐
- [BZOJ4573][[Zjoi2016]大森林][LCT建虚点]
[BZOJ4573][[Zjoi2016]大森林][LCT建虚点] 题意懒得写了.... 思路: 建LCT的时候我们可以引入虚点.对于所有的1操作,新建一个没有权值的虚点,然后对于0操作,可以把新建的 ...
- BZOJ4573:[ZJOI2016]大森林——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=4573 https://www.luogu.org/problemnew/show/P3348#sub ...
- [ZJOI2016]大森林
Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例 ...
- bzoj 4573: [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...
- [2019.3.20]BZOJ4573 [Zjoi2016]大森林
发现一个重要的性质:由于不存在删点的操作,所以之后的加点并不会对之前的询问的答案造成影响. 所以我们可以先处理修改,再处理询问. 考虑从左到右扫描每一颗树,每次将前一棵树通过一些修改变为后一棵树. 发 ...
- BZOJ4573 : [Zjoi2016]大森林
扫描线,从左到右依次处理每棵树. 用set按时间顺序维护影响了这棵树的所有操作,那么一个点的父亲就是它前面第一个操作1. 用Splay维护树的括号序列,那么两点间的距离就是括号数量减去匹配的括号个数. ...
- 「ZJOI2016」大森林 解题报告
「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...
- bzoj 4573 大森林
bzoj 4573 大森林 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后. 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理 ...
- 3825. 逃离大森林
3825. 逃离大森林 题目链接 #include <bits/stdc++.h> #define x first #define y second using namespace std ...
最新文章
- Ubuntu下压缩解压文件
- 启动maven项目在eclipse中报错 Can‘t find class [×××] for bean with name '××' defined in class path resource
- 乐高收割机器人_乐高圣诞45002作品来啦!——驯鹿拉雪橇、圣诞树、圣诞棒棒糖...
- Quartz定时任务的基本搭建
- “四方定理”--蓝桥杯
- c++ 测试串口速率_纳米软件案例之电流控制测试系统
- Linux知识积累(2)dirname的使用方法
- 二维码生成原理及解析代码
- 员工评分系统现场发布小感
- win10安装出现“Windows以保护你的电脑” Micosoft Defender SmartScreen阻止了无法识别的应用启动。运行此应用可能会导致你的电脑存在风险。
- html5 图片缩放 鼠标滚轮,鼠标滚轮实现图片的放大缩小
- ps cs6选择并遮住在哪
- 节点精灵 控制循环时间
- 武-NC15522(Dijsktra最短路算法)
- 耗时五个月的项目实训——影行App
- D3 二维图表的绘制系列(二十六)盒须图
- java 做日历_java编程实现日历
- Android 安卓动画 属性动画 - 渐变/透明度 动画
- 腰椎间盘突出症的自我疗法
- 对于健康只有失去才懂得珍惜