码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj-2002 Bounce 弹飞绵羊

时间:2015-08-15 18:26:26      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:bzoj   lct   

题意:

直线上有一排n个弹力装置,每个弹力装置会将绵羊弹到下ki个弹力装置处;

如果没有了则绵羊被弹飞。。

问每个绵羊被弹了几次弹飞;

可能会修改弹力装置的k值;

n<=200000,m<=100000;


题解:

裸的LCT吧;

所以下面的启发式合并Splay是啥鬼;

有人说这题边有向,和无向边不一样;

然而有个卵区别,把终点作为根不就有向了吗!

反正切了上一题这一题也不难吧;

维护个size之后,把终点作为根再access(x);

这时的Splay就是x弹飞的路线啦,Splay(x)之后x的左子树大小就是答案咯;

其实也是整棵Splay的大小-1,因为x的重儿子在access时砍掉了嘛;

LCT是啥啥的还是戳上一篇。。


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 210000
#define which(x) (ch[fa[x]][1]==x)
using namespace std;
int fa[N],ch[N][2],size[N],to[N],root;
bool rt[N],cov[N];
void Pushup(int x)
{
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void reverse(int x)
{
	swap(ch[x][0],ch[x][1]);
	cov[x]^=1;
}
void Pushdown(int x)
{
	if(cov[x])
	{
		reverse(ch[x][0]);
		reverse(ch[x][1]);
		cov[x]=0;
	}
}
void down(int x)
{
	if(!rt[x])	down(fa[x]);
	Pushdown(x);
}
void Rotate(int x)
{
	int f=fa[x];
	bool k=which(x);
	if(rt[f])	rt[f]^=rt[x]^=1;
	else		ch[fa[f]][which(f)]=x;
	ch[f][k]=ch[x][!k];
	ch[x][!k]=f;
	fa[ch[f][k]]=f;
	fa[x]=fa[f];
	fa[f]=x;
	size[x]=size[f];
	Pushup(f);
}
void Splay(int x)
{
	down(x);
	while(!rt[x])
	{
		int f=fa[x];
		if(rt[f])
		{
			Rotate(x);
			return ;
		}
		if(which(x)^which(f))
			Rotate(x);
		else
			Rotate(f);
		Rotate(x);
	}
}
void access(int x)
{
	int y=0;
	while(x)
	{
		Splay(x);
		rt[ch[x][1]]=1;
		rt[y]=0;
		ch[x][1]=y;
		Pushup(x);
		y=x,x=fa[x];
	}
}
void Mtr(int x)
{
	access(x);
	Splay(x);
	reverse(x);
}
void Link(int x,int y)
{
	Mtr(x);
	fa[x]=y;
}
void Cut(int x,int y)
{
	Mtr(x);
	access(y);
	Splay(x);
	ch[x][1]=0,fa[y]=0;
	rt[y]=1;
	Pushup(x);
}
int Query(int x)
{
	Mtr(root);
	access(x);
	Splay(x);
	return size[ch[x][0]];
}
int main()
{
	int n,m,i,j,k,x,y,op;
	scanf("%d",&n);
	root=n+1;
	for(i=1;i<=n+1;i++)
		rt[i]=1,size[i]=1;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&k);
		to[i]=min(i+k,root);
		Link(i,to[i]);
	}
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d",&x),x++;
			printf("%d\n",Query(x));
		}
		else
		{
			scanf("%d%d",&x,&k),x++;
			Cut(x,to[x]);
			to[x]=min(x+k,root);
			Link(x,to[x]);
		}
	}
	return 0;
}



bzoj-2002 Bounce 弹飞绵羊

标签:bzoj   lct   

原文地址:http://blog.csdn.net/ww140142/article/details/47683051

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!