JZOJ 5107. 【GDSOI2017】 中学生数据结构题

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

Description

Description

Input

第一行有一个整数 N,表示 S 国城市的数量。
接下来有 N-1 行,每行两个数 u,v 表示一条道路。
第 N+1 行为一个整数 Q,表示接下来有 Q 个操作。
接下来有 Q 行,每行表示一个操作,格式如题目描述所示。

Output

   对于每一个 QUERY 操作,输出一个数,表示询问的当前编号为 X 和编号为 Y 的城市的最短路径间的城市 (包括编号为 X 的城市和编号为 Y 的城市)的士兵总和。

Sample Input

Sample Input1:

5
1 2
1 3
3 4
3 5
6
ADD 1 5 2
ADD 3 4 1
QUERY 1 4
SHIFT 1 4
ADD 5 4 1
QUERY 4 5

Sample Input12:

5
1 2
2 3
3 4
4 5
5
ADD 1 3 2
ADD 3 5 1
SHIFT 2 4
QUERY 1 3
QUERY 1 5

Sample Output

Sample Output1:

6
10

Sample Output2:

5
9

Data Constraint

Data Constraint

Solution

  • 刚了这么久终于过了……

  • 还是套路,一棵形态LCT,维护的是当前树的形态;

  • 一个权值LCT(Splay),维护的是当前形态下形态LCT中每个点对应的权值。

  • 按要求操作即可,时间复杂度 O ( n   l o g   n ) O(n\ log\ n)

Code

#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int tot,top;
int first[N],nex[N<<1],en[N<<1];
int st[N];
char ty[7];
struct value
{
	int fa[N],s[N][2],size[N];
	LL key[N],sum[N],tag[N];
	bool rev[N];
	inline bool pd(int x)
	{
		return x==s[fa[x]][1];
	}
	inline void update(int x)
	{
		size[x]=size[s[x][0]]+size[s[x][1]]+1;
		sum[x]=sum[s[x][0]]+sum[s[x][1]]+key[x];
	}
	inline void reverse(int x)
	{
		if(x) swap(s[x][0],s[x][1]),rev[x]^=1;
	}
	inline void modify(int x,LL val)
	{
		if(x)
		{
			sum[x]+=size[x]*val;
			key[x]+=val;
			tag[x]+=val;
		}
	}
	inline void down(int x)
	{
		if(rev[x])
		{
			rev[x]=false;
			reverse(s[x][0]);
			reverse(s[x][1]);
		}
		if(tag[x])
		{
			modify(s[x][0],tag[x]);
			modify(s[x][1],tag[x]);
			tag[x]=0;
		}
	}
	inline void rotate(int x)
	{
		down(x);
		int y=fa[x],w=pd(x);
		if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
		if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
		s[fa[y]=x][w^1]=y;
		update(y);
	}
	inline void splay(int x)
	{
		for(int y;y=fa[x];rotate(x))
			if(fa[y]) rotate(pd(x)==pd(y)?y:x);
		update(x);
	}
	inline int root(int x)
	{
		while(fa[x]) x=fa[x];
		return x;
	}
	int kth(int x,int k)
	{
		down(x);
		if(size[s[x][0]]+1==k) return x;
		if(size[s[x][0]]+1>k) return kth(s[x][0],k);
		return kth(s[x][1],k-size[s[x][0]]-1);
	}
}v;
struct shape
{
	int fa[N],s[N][2],size[N],rt[N];
	bool rev[N];
	inline bool pd(int x)
	{
		return x==s[fa[x]][1];
	}
	inline bool isroot(int x)
	{
		return s[fa[x]][0]^x && s[fa[x]][1]^x;
	}
	inline void reverse(int x)
	{
		if(x) swap(s[x][0],s[x][1]),rev[x]^=1;
	}
	inline void update(int x)
	{
		size[x]=size[s[x][0]]+size[s[x][1]]+1;
	}
	inline void down(int x)
	{
		if(rev[x])
		{
			rev[x]=false;
			reverse(s[x][0]);
			reverse(s[x][1]);
		}
	}
	inline void rotate(int x)
	{
		int y=fa[x],w=pd(x);
		if((fa[x]=fa[y]) && !isroot(y)) s[fa[y]][pd(y)]=x;
		if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
		s[fa[y]=x][w^1]=y;
		rt[x]=rt[y],rt[y]=0;
		update(y);
	}
	inline void splay(int x)
	{
		for(int y=st[top=1]=x;!isroot(y);y=fa[y]) st[++top]=fa[y];
		while(top) down(st[top--]);
		for(int y;!isroot(x);rotate(x))
			if(!isroot(y=fa[x])) rotate(pd(x)==pd(y)?y:x);
		update(x);
	}
	inline void access(int x)
	{
		for(int y=0;x;x=fa[y=x])
		{
			splay(x);
			int xx=v.root(rt[x]);
			xx=v.kth(xx,size[s[x][0]]+1);
			v.splay(rt[x]=xx);
			if(s[x][1])
			{
				rt[s[x][1]]=v.s[xx][1];
				v.fa[v.s[xx][1]]=0;
				v.s[xx][1]=s[x][1]=0;
			}
			if(y)
			{
				s[x][1]=y;
				v.s[xx][1]=v.root(rt[y]);
				if(v.s[xx][1]) v.fa[v.s[xx][1]]=xx;
			}
			v.update(xx);
			update(x);
		}
	}
	inline void mkroot(int x)
	{
		access(x),splay(x),reverse(x);
		int xx=v.root(rt[x]);
		xx=v.kth(xx,size[s[x][0]]+1);
		v.splay(xx);
		v.reverse(xx);
	}
}s;
inline int read()
{
	int X=0,w=0; char ch=0;
	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
	while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
	return w?-X:X;
}
inline void insert(int x,int y)
{
	nex[++tot]=first[x];
	first[x]=tot;
	en[tot]=y;
}
void dfs(int x,int y)
{
	s.fa[x]=y;
	s.size[x]=v.size[x]=1;
	s.rt[x]=x;
	for(int i=first[x];i;i=nex[i])
		if(en[i]^y) dfs(en[i],x);
}
int main()
{
	freopen("shift.in","r",stdin);
	freopen("shift.out","w",stdout);
	int n=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		insert(x,y);
		insert(y,x);
	}
	dfs(1,0);
	int q=read();
	while(q--)
	{
		scanf("%s",&ty);
		int x=read(),y=read();
		if(ty[0]=='S' && x==y) continue;
		s.mkroot(x);
		s.access(y);
		s.splay(y);
		int yy=s.rt[y];
		v.splay(yy);
		yy=v.kth(yy,s.size[s.s[y][0]]+1);
		v.splay(yy);
		if(ty[0]=='A')
		{
			int z=read();
			v.modify(yy,z);
		}else
		if(ty[0]=='S')
		{
			int pos=v.s[yy][0];
			v.s[yy][0]=0;
			v.fa[pos]=0;
			pos=v.kth(pos,1);
			v.splay(pos);
			v.fa[pos]=yy;
			v.s[yy][1]=pos;
			v.update(yy);
		}else
			printf("%lld\n",v.sum[yy]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liyizhixl/article/details/85368654
今日推荐