bzoj 4573: [Zjoi2016]大森林
2018-04-28 16:57
344 查看
Description
小Y家里有一个大森林,里面有n棵树,编号从1到n。一开始这些树都只是树苗,只有一个节点,标号为1。这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力。小Y掌握了一种魔法,能让第l棵树
到第r棵树的生长节点长出一个子节点。同时她还能修改第l棵树到第r棵树的生长节点。她告诉了你她使用魔法的
记录,你能不能管理她家的森林,并且回答她的询问呢?
Solution
有点神仙,看了题解的做法首先显然要离线,否则空间都是错的,这样维护一棵树就好了
然后发现都是区间修改,扫描线维护一下节点就好了
但是还有删除节点这样的操作,复杂度保证不了
不如先把树的形态都建出来,对于 \(1\) 到 \(n\) 的公共部分我们一起考虑,不同的部分就直接新建节点
考虑维护添加,删除操作的复杂度
我们每产生一个新的生长节点就新建一个虚点,然后把新长出来的都接上去
如果按加入时间考虑的话,有很多连续的节点都是同一个父亲,所以我们用一个虚点暂时代替它们的父亲
然后对于 \(1\) 到 \(n\) 的不同的树,它们的父亲是不一样的,因为建立了这个虚点,所以只需要把虚点的父亲变一下,就可以达到把所有的点的父亲都改变的效果了
具体的也说不清楚,看代码比较直观.....
#include<bits/stdc++.h> using namespace std; template<class T>void gi(T &x){ int f;char c; for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1; for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f; } const int N=4e5+10; int n,m,ch [2],fa ,a ,w ; inline void upd(int x){w[x]=w[ch[x][0]]+w[ch[x][1]]+a[x];} inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} inline void rotate(int x){ int y=fa[x];bool t=ch[y][1]==x; ch[y][t]=ch[x][!t];fa[ch[y][t]]=y; ch[x][!t]=y;fa[x]=fa[y]; if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x; fa[y]=x;upd(y);upd(x); } inline void splay(int x){ while(!isrt(x)){ int y=fa[x],p=fa[y]; if(isrt(y))rotate(x); else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x); else rotate(x),rotate(x); } } inline int access(int x){ int y=0; while(x)splay(x),ch[x][1]=y,upd(x),x=fa[y=x]; return y; } inline void link(int x,int y){ access(x);splay(x);fa[x]=y; } inline void cut(int x){ access(x);splay(x);fa[ch[x][0]]=0;ch[x][0]=0;upd(x); } inline int query(int x,int y){ int ret=0,t; access(x);splay(x);ret+=w[x]; t=access(y);splay(y);ret+=w[y]; access(t);splay(t);ret-=w[t]<<1; return ret; } int L ,R ,id ,cnt=2,ans ,top=0; struct data{ int ty,p,x,y; inline bool operator <(const data &t)const{ if(p!=t.p)return p<t.p; return ty<t.ty; } }q ; int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); cin>>n>>m; int op,l,r,x,y=2,tp=0,ID=1; L[1]=1;R[1]=n;id[1]=1;w[1]=a[1]=1; L[2]=1;R[2]=n;w[2]=a[2]=0;link(2,1); for(int i=1;i<=m;i++){ gi(op);gi(l);gi(r); if(op==0){ a[++cnt]=1;w[cnt]=1;L[++ID]=l;R[ID]=r;id[ID]=cnt; link(cnt,y); } else if(op==1){ gi(x); a[++cnt]=0;w[cnt]=0;l=max(l,L[x]);r=min(r,R[x]); if(l<=r){ link(cnt,y); q[++top]=(data){-1,l,cnt,id[x]}; q[++top]=(data){-1,r+1,cnt,y}; y=cnt; } } else gi(x),q[++top]=(data){++tp,l,id[r],id[x]}; } sort(q+1,q+top+1); for(int i=1,j=1;i<=n;i++){ while(j<=top && q[j].p==i){ if(q[j].ty==-1)cut(q[j].x),link(q[j].x,q[j].y); else ans[q[j].ty]=query(q[j].x,q[j].y); j++; } } for(int i=1;i<=tp;i++)printf("%d\n",ans[i]); return 0; }
相关文章推荐
- [BZOJ4573][ZJOI2016]大森林(LCT建虚点)
- [LCT || splay维护括号序列] BZOJ 4573 [Zjoi2016]大森林
- [BZOJ4573][UOJ#195][Zjoi2016][LCT][离线]大森林
- bzoj 4573: [Zjoi2016]大森林 lct
- [bzoj4573][UOJ#195][ZJOI2016]大森林
- BZOJ4573 : [Zjoi2016]大森林
- [BZOJ4573][[Zjoi2016]大森林][LCT建虚点]
- Bzoj4573: [Zjoi2016]大森林
- BZOJ4573:[ZJOI2016]大森林——题解
- [BZOJ4573][ZJOI2016]大♂森林
- [BZOJ4455][ZJOI2016]数星星(容斥DP)
- bzoj 4574: [Zjoi2016]线段树 动态规划
- Bzoj4456 [Zjoi2016]旅行者
- bzoj 4455: [Zjoi2016]小星星 (容斥原理+DP)
- [BZOJ4455][Zjoi2016]小星星(容斥原理+树形dp)
- [容斥 状压DP 树形DP] BZOJ 4455 [Zjoi2016]小星星 & UOJ #185 【ZJOI2016】小星星
- 【bzoj4455】[Zjoi2016]小星星
- [分治 最短路] BZOJ 4456 [Zjoi2016]旅行者
- 【BZOJ 4455】 4455: [Zjoi2016]小星星 (容斥原理+树形DP)
- 【BZOJ 4574】【ZJOI 2016】线段树