LCT+树剖+线段树--bzoj4817: [Sdoi2017]树点涂色

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84622625

传送门
bzoj3379有异曲同工之妙
也是用树剖+线段树的思想维护 d f s dfs 序,然后查询区间最大值

1操作就是 l c t lct a c c e s s access ,同bzoj3379
2操作就是 f ( x ) + f ( y ) 2 × f ( l c a ( x , y ) ) f(x)+f(y)-2\times f(lca(x,y)) ,也可以用树剖+线段树
3操作就是线段树区间最大值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 100005
#define ls ch[x][0]
#define rs ch[x][1]
#define lls cur<<1
#define rrs cur<<1|1
#define len(x) (r[x]-l[x]+1)
using namespace std;

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}
inline int max(int x,int y){return x>y?x:y;}

int n,m,cnt,head[N],to[N<<1],nxt[N<<1],root=1;
int num,dfn[N],dep[N],fa[N],top[N],rk[N],siz[N],son[N];

inline void add(int x,int y){
	to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;
}

void dfs1(int u,int fat){
	siz[u]=1; int maxson=-1;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i]; if(v==fat) continue;
		dep[v]=dep[u]+1; fa[v]=u;
		dfs1(v,u); siz[u]+=siz[v];
		if(siz[v]>maxson) maxson=siz[v],son[u]=v;
	}
}

void dfs2(int u,int t){
	top[u]=t; dfn[u]=++num; rk[num]=u;
	if(!son[u]) return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(!dfn[v]) dfs2(v,v);
	}
}

inline int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	return dep[x]<dep[y]?x:y;
}

int mx[N<<2],lazy[N<<2],l[N<<2],r[N<<2];

inline void Spushup(int cur){
	mx[cur]=max(mx[lls],mx[rrs]);
}

void build(int cur,int L,int R){
	if(L==R){
		mx[cur]=dep[rk[L]]+1; l[cur]=r[cur]=L; return;
	}
	int mid=(L+R)>>1;
	build(lls,L,mid); build(rrs,mid+1,R);
	l[cur]=l[lls],r[cur]=r[rrs];
	Spushup(cur);
}

inline void Spushdown(int cur){
	if(lazy[cur]!=0){
		int t=lazy[cur]; lazy[cur]=0;
		mx[lls]+=t; lazy[lls]+=t;
		mx[rrs]+=t; lazy[rrs]+=t;
	}
}

void Supdate(int cur,int L,int R,int c){
	if(L<=l[cur] && r[cur]<=R){
		mx[cur]+=c; lazy[cur]+=c;
		return;
	}
	Spushdown(cur);
	int mid=(l[cur]+r[cur])>>1;
	if(L<=mid) Supdate(lls,L,R,c);
	if(mid<R) Supdate(rrs,L,R,c);
	Spushup(cur);
}

int query(int cur,int L,int R){
	if(L<=l[cur] && r[cur]<=R) return mx[cur];
	Spushdown(cur); int mid=(l[cur]+r[cur])>>1,res=0;
	if(L<=mid) res=max(res,query(lls,L,R));
	if(mid<R) res=max(res,query(rrs,L,R));
	return res;
}

namespace lct{
	int f[N],ch[N][2],rev[N],tl[N],tr[N];
	inline int get(int x){return ch[f[x]][1]==x;}
	inline int isrt(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
	inline void update(int x){
		if(!ls) tl[x]=x; else tl[x]=tl[ls];
		if(!rs) tr[x]=x; else tr[x]=tr[rs];
	}
	inline void rever(int x){rev[x]^=1;swap(ls,rs),swap(tl[x],tr[x]);}
	inline void pushdown(int x){
		if(rev[x]){
			if(ls) rever(ls);
			if(rs) rever(rs);
			rev[x]=0;
		}
	}
	void pushup(int x){if(!isrt(x)) pushup(f[x]);pushdown(x);}
	inline void rotate(int x){
		int old=f[x],oldf=f[old],wh=get(x);
		if(!isrt(old)) ch[oldf][get(old)]=x;
		f[x]=oldf; f[old]=x;
		ch[old][wh]=ch[x][wh^1]; f[ch[old][wh]]=old;
		ch[x][wh^1]=old;
		update(old); update(x);
	}
	inline void splay(int x){
		pushup(x);
		for(;!isrt(x);rotate(x))
			if(!isrt(f[x])) rotate(get(x)==get(f[x])?f[x]:x);
	}
	inline void access(int x){
		for(int y=0;x;y=x,x=f[x]){
			splay(x);
			if(rs) Supdate(1,dfn[tl[rs]],dfn[tl[rs]]+siz[tl[rs]]-1,1);
			rs=y;
			if(rs) Supdate(1,dfn[tl[rs]],dfn[tl[rs]]+siz[tl[rs]]-1,-1);
			update(x);
		}
	}
	inline void makeroot(int x){
		access(x); splay(x); rever(x);
	}
};

int main(){
	n=rd(); m=rd();
	for(int i=1;i<n;i++){
		int x=rd(),y=rd();
		add(x,y); add(y,x);
	}
	dfs1(root,0); dfs2(root,root);
	for(int i=1;i<=n;i++) lct::tl[i]=lct::tr[i]=i,lct::f[i]=fa[i];
	build(1,1,n); int opt,x,y;
	while(m--){
		opt=rd();
		if(opt==1){
			x=rd();
			lct::access(x);
		}
		if(opt==2){
			x=rd(); y=rd(); int z=LCA(x,y);
			printf("%d\n",query(1,dfn[x],dfn[x])+query(1,dfn[y],dfn[y])-2*query(1,dfn[z],dfn[z])+1);
		}
		if(opt==3){
			x=rd();
			printf("%d\n",query(1,dfn[x],dfn[x]+siz[x]-1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/84622625