BZOJ4530 BJOI 2014 大融合 LCT维护子树信息
2017-12-04 16:52
477 查看
BZOJ4530 大融合
Description小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。
这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够
联通的树上路过它的简单路径的数量。
例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因
为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的
询问。
Input
第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。
接下来的Q行,每行是如下两种格式之一:
A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。
Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。
1≤N,Q≤100000
题目中要求的负载就是以一条边端点为根的两个子树的大小相乘。而动态加边的操作很容易想到LCT。一般的LCT通过伸展树维护的是一条链上的信息,但这并不意味着不能使用LCT。
开两个数组Size[x]和sz[x],分别表示以x为根的子树的大小、x的虚儿子的Size和。那么有递推式:
Size[x]=Size[ls[x]]+Size[rs[x]]+1+sz[x]
也就是把Size划分为了伸展树里节点的Size之和、虚儿子的Size之和。那么现在的问题在于如何维护sz数组。注意到本题用到的Access操作中,每次向上跳都最多只会将一条实边改为虚边、一条虚边改为实边;Link操作直接是给一个点增加一个虚儿子。所以在这两个操作中维护一下sz即可。
#include<stdio.h> #include<algorithm> #define MAXN 200005 #define ll long long using namespace std; int N,Q; int ls[MAXN],rs[MAXN],fa[MAXN],rev[MAXN],Size[MAXN],sz[MAXN]; bool isrt(int x){return ls[fa[x]]!=x&&rs[fa[x]]!=x;} void Update(int p) { Size[p]=Size[ls[p]]+Size[rs[p]]+sz[p]+1; //Size[p]=Size[rs[p]]+sz[p]+1; } void Putdown(int p) { if(rev[p]==0)return; rev[p]=0;rev[ls[p]]^=1;rev[rs[p]]^=1; swap(ls[p],rs[p]); } void Zig(int x) { int y=fa[x],z=fa[y]; if(!isrt(y)) { if(ls[z]==y)ls[z]=x; else rs[z]=x; } fa[x]=z;fa[y]=x;fa[rs[x]]=y; ls[y]=rs[x];rs[x]=y; Update(y);Update(x); } void Zag(int x) { int y=fa[x],z=fa[y]; if(!isrt(y)) { if(ls[z]==y)ls[z]=x; else rs[z]=x; } fa[x]=z;fa[y]=x;fa[ls[x]]=y; rs[y]=ls[x];ls[x]=y; Update(y);Update(x); } int dc5d s[MAXN],Top; void Splay(int x) { int i,y,z; s[++Top]=x; for(i=x;!isrt(i);i=fa[i])s[++Top]=fa[i]; while(Top)Putdown(s[Top--]); while(!isrt(x)) { y=fa[x];z=fa[y]; if(isrt(y)) { if(ls[y]==x)Zig(x); else Zag(x); } else { if(ls[z]==y) { if(ls[y]==x)Zig(y),Zig(x); else Zag(x),Zig(x); } else { if(rs[y]==x)Zag(y),Zag(x); else Zig(x),Zag(x); } } } } void Access(int x) { int t=0; while(x) { Splay(x); sz[x]=sz[x]-Size[t]+Size[rs[x]]; rs[x]=t; Update(x); t=x;x=fa[x]; } } void SetRt(int x) { Access(x);Splay(x);rev[x]^=1; } void Link(int x,int y) { SetRt(x);SetRt(y); sz[y]+=Size[x]; Update(y); Splay(y); fa[x]=y; } int main() { int i,x,y; char op[3]; ll Ans; scanf("%d%d",&N,&Q); for(i=1;i<=N;i++)Size[i]=1; while(Q--) { scanf("%s%d%d",op,&x,&y); if(op[0]=='A')Link(x,y); else { SetRt(x);Access(y); Ans=sz[y]+1; SetRt(y);Access(x); Ans*=(sz[x]+1); printf("%lld\n",Ans); } } }
相关文章推荐
- 【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息
- [BZOJ4530][Bjoi2014][LCT维护子树信息]大融合
- 【BZOJ4530】[Bjoi2014]大融合 LCT维护子树信息
- bzoj 4530: [Bjoi2014]大融合 lct维护子树信息
- BZOJ 4530: [Bjoi2014]大融合 lct维护子树信息
- BZOJ 4530 [Bjoi2014]大融合 LCT维护子树信息
- 【LCT维护子树信息】BZOJ4530(Bjoi2014)[大融合]题解
- [BZOJ]4530 [BJOI2014] 大融合 LCT维护子树信息
- bzoj4530 [Bjoi2014]大融合(LCT维护子树大小)
- [BZOJ4530]-大融合-LCT维护子树信息
- LCT维护子树信息(BZOJ4530:[BJOI2014]大融合)
- 【bzoj 4530】大融合(LCT维护子树信息)
- bzoj4530 [Bjoi2014]大融合 (LCT维护子树信息)
- JZOJ 3766【BJOI2014】大融合(lct维护子树大小)
- BZOJ 4530 [Bjoi2014]大融合 [LCT]
- BZOJ_4530_[Bjoi2014]大融合_LCT
- [bzoj4530][Bjoi2014]大融合_LCT
- BZOJ4530:[BJOI2014]大融合(LCT维护子树)
- [BZOJ4530][Bjoi2014]大融合(LCT)
- BZOJ.4530.[BJOI2014]大融合(LCT)