博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ZJOI2016]大森林(LCT)
阅读量:5282 次
发布时间:2019-06-14

本文共 2661 字,大约阅读时间需要 8 分钟。

题目描述

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

小Y掌握了一种魔法,能让第l棵树到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?

题解

这题太神了,废了我一下午。

看到区间操作,就可以想到差分或者扫描线,我们会发现这题基本没有好的方法去执行批量操作,所以我们要用扫描线。

这道题的操作有,区间生长一个点,区间换父亲。

我们对于每个1操作新建一个虚点,然后把它们串起来,然后把每个0操作长出来的点挂在上一个虚点上,然后一通做完之后的树长这样(白点为虚点,黑点为实点)。

时间从上到下为从早到晚。

对于一个换父亲操作,假如说我们要对最下面的白点对应的换父亲的操作换到右边从上到下第二个黑点上,那么我们可以这样。

可以手玩一下,所有有效节点对应的deep是对的。

然后我们用LCT维护这一过程,求两点

注意判断1操作的作用范围。

代码

#include
#include
#include
#define N 200002using 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 getinline 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
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

你可能感兴趣的文章
Suite3.4.7和Keil u3自带fx2.h、fx2regs.h文件的异同
查看>>
打飞机游戏【来源于Crossin的编程教室 http://chuansong.me/account/crossincode 】
查看>>
[LeetCode] Merge Intervals
查看>>
Linux编程简介——gcc
查看>>
2019年春季学期第四周作业
查看>>
rotate the clock
查看>>
数据库02 /MySQL基础数据类型以及多表之间建立联系
查看>>
Python并发编程04/多线程
查看>>
CF461B Appleman and Tree
查看>>
CF1215E Marbles
查看>>
BZOJ2339 HNOI2011卡农(动态规划+组合数学)
查看>>
octave基本操作
查看>>
axure学习点
查看>>
WPF文本框只允许输入数字[转]
查看>>
dom4j 通用解析器,解析成List<Map<String,Object>>
查看>>
第一个项目--用bootstrap实现美工设计的首页
查看>>
使用XML传递数据
查看>>
TYVJ.1864.[Poetize I]守卫者的挑战(概率DP)
查看>>
0925 韩顺平java视频
查看>>
iOS-程序启动原理和UIApplication
查看>>