[BZOJ4573][LCT]ZJOI2016:大森林

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88672178

BZOJ4573

巧妙的思路:显然分别维护每棵树是不可能的,时间空间都无法接受
所以换个想法,发现操作对于没换生长点时候的树都是一致的,所以可以直接改变一下策略,维护同一棵树
然后考虑修改生长点,可以离线操作,先保存所有操作和询问,加点就加到它最近新建的点就好了

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=2e5+5;
namespace LCT{
	int ls[N],rs[N],siz[N],s[N],fa[N];
	inline int isrs(int x){return rs[fa[x]]==x;}
	inline bool isroot(int x){
		if(!x) return true;
		return ls[fa[x]]!=x && rs[fa[x]]!=x;
	}
	inline void pushup(int x){siz[x]=siz[ls[x]]+siz[rs[x]]+s[x];}
	inline void rotate(int x){
		int y=fa[x],z=fa[y],b=(ls[y]==x?rs[x]:ls[x]);
		if(z && !isroot(y)) (ls[z]==y?ls[z]:rs[z])=x;
		fa[x]=z,fa[y]=x,b?fa[b]=y:0;
		if(ls[y]==x) rs[x]=y,ls[y]=b;
		else ls[x]=y,rs[y]=b;
		pushup(y);pushup(x);
	}
	inline void splay(int x){
		while(!isroot(x)){
			while(!isroot(fa[x])){
				if(isrs(fa[x])==isrs(x)) rotate(fa[x]);
				else rotate(x);
			}
			rotate(x);
		}
		pushup(x);
	}
	inline int access(int x){int y=0;for(;x;y=x,x=fa[x]){splay(x);rs[x]=y;pushup(x);}return y;}
	inline void link(int x,int y){splay(x);fa[x]=y;}
	inline void cut(int x){access(x);splay(x);ls[x]=fa[ls[x]]=0;pushup(x);}
}
using namespace LCT;
int n,m,tot=0,cnt=0,now,cur=0;
int l[N],r[N],a[N],ans[N];
struct Q{int pos,op,x,y;}q[N<<2];
inline bool cmp(Q a,Q b){if(a.pos==b.pos) return a.op<b.op;return a.pos<b.pos;}
inline void ins(int x){s[tot+1]=siz[++tot]=x;}
int main(){
	freopen("lx.in","r",stdin);
	n=read();m=read();
	ins(1);a[++cnt]=l[1]=1;r[1]=n;
	ins(0);now=2;link(2,1);
	int k,op,x,y;
	for(int i=1;i<=m;i++){
		op=read();
		if(!op){
			l[++cnt]=read();r[cnt]=read();
			ins(1);a[cnt]=tot;
			q[++cur]=(Q){1,i-m,tot,now};
		}
		else if(op==1){
			x=read();y=read();k=read();
			x=max(x,l[k]),y=min(y,r[k]);
			if(x<=y){
				ins(0);
				if(x>1) link(tot,now);
				q[++cur]=(Q){x,i-m,tot,a[k]};
				q[++cur]=(Q){y+1,i-m,tot,now};now=tot;
			}
		}
		else{
			k=read();x=read();y=read();
			q[++cur]=(Q){k,i,a[x],a[y]};
		}
	}
	sort(q+1,q+cur+1,cmp);
	memset(ans,-1,sizeof(ans));
	for(int i=k=1;i<=n;i++){
		for(;k<=cur && q[k].pos==i;k++){
			if(q[k].op>0){
				access(q[k].x);splay(q[k].x);ans[q[k].op]=siz[q[k].x];
				x=access(q[k].y);splay(q[k].y);ans[q[k].op]+=siz[q[k].y];
				access(x);splay(x);ans[q[k].op]-=siz[x]<<1;
			}
			else{cut(q[k].x);link(q[k].x,q[k].y);}
		}
	}
	for(int i=1;i<=m;i++) if(ans[i]!=-1) cout<<ans[i]<<"\n";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/88672178
今日推荐