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

bzoj-1125 Poc

时间:2015-09-14 12:18:43      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:bzoj   poi   splay   hash   

题意:

给出n个字符串,长度均为len;

有m次操作,每次将两个字符交换;

求每个字符串在任何时点上,与相同的它最多的字符串个数;

n<=1000,len<=100,m<=100000;


题解:

Poi!

字符串长度很小,我们先考虑到用Hash来判断字符串的相同;

这些部分很简单,但是统计任意时点对某个字符串的答案是很难的;

因为如果暴力更新的话复杂度是O(nm),所以不能这么搞;

而延迟更新也没有什么好办法,只能去找打标记的数据结构了;

这里我写了一个Splay,以Hash值大小为关键字排序;

修改时先将其转到根删掉,然后再修改之后插回去,

之后将Hash值相同的一段提出来打标记更新答案;

这样每次的复杂度是O(len+logn)的。。

注意将同一个字符串中的字符交换时,不要让它被删两次哦2333;


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1100
#define seed 1331
#define which(x) (ch[fa[x]][1]==x)
using namespace std;
typedef unsigned long long ll;
int n,len;
int size[N],fa[N],ch[N][2],cov[N],ans[N],root;
char str[N][111];
ll val[N],pow[111];
void Pushup(int x)
{
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void Pushdown(int x)
{
	if(cov[x])
	{
		ans[ch[x][0]]=max(ans[ch[x][0]],cov[x]);
		cov[ch[x][0]]=max(cov[ch[x][0]],cov[x]);
		ans[ch[x][1]]=max(ans[ch[x][1]],cov[x]);
		cov[ch[x][1]]=max(cov[ch[x][1]],cov[x]);
		cov[x]=0;
	}
}
void Rotate(int x)
{
	int f=fa[x];
	bool k=which(x);
	Pushdown(f),Pushdown(x);
	ch[f][k]=ch[x][!k];
	ch[x][!k]=f;
	ch[fa[f]][which(f)]=x;
	fa[x]=fa[f];
	fa[f]=x;
	fa[ch[f][k]]=f;
	Pushup(f);
	Pushup(x);
}
void Splay(int x,int g)
{
	while(fa[x]!=g)
	{
		int f=fa[x];
		if(fa[f]==g)
		{
			Rotate(x);
			break;
		}
		if(which(x)^which(f))
			Rotate(x);
		else
			Rotate(f);
		Rotate(x);
	}
	if(!g)	root=x;
}
int pre(ll v)
{
	int p=root,ret=root;
	while(p)
	{
		if(v>val[p])
			ret=p,p=ch[p][1];
		else
			p=ch[p][0];
	}
	return ret;
}
int sub(ll v)
{
	int p=root,ret;
	while(p)
	{
		if(v<val[p])
			ret=p,p=ch[p][0];
		else
			p=ch[p][1];
	}
	return ret;
}
void Down(int x)
{
	if(!x)	return ;
	Pushdown(x);
	Down(ch[x][0]);
	Down(ch[x][1]);
}
void Insert(int x)
{
	int l=pre(val[x]),r=sub(val[x]);
	Splay(l,0),Splay(r,l);
	int t=ch[r][0];
	fa[t]=x,ch[x][0]=t;
	fa[x]=r,ch[r][0]=x;
	Pushup(x),Pushup(r),Pushup(l);
	ans[x]=max(ans[x],size[x]);
	cov[x]=max(cov[x],size[x]);
}
void del(int x)
{
	Splay(x,0);
	int p=ch[x][1];
	while(ch[p][0])
		p=ch[p][0];
	Splay(p,x);
	ch[p][0]=ch[x][0];
	fa[ch[p][0]]=p,fa[p]=0;
	root=p;
	Pushup(p);
	ch[x][0]=ch[x][1]=0;
	size[x]=1;
}
void init()
{
	pow[0]=1;
	for(int i=1;i<=len;i++)
		pow[i]=pow[i-1]*seed;
	root=n+1,size[n+1]=2,ch[n+1][1]=n+2;
	size[n+2]=1,fa[n+2]=n+1;
	val[n+1]=0,val[n+2]=(1ll<<64)-1;
}
int main()
{
	int m,i,j,k,a,b,x,y;
	scanf("%d%d%d",&n,&len,&m);
	init();
	for(i=1;i<=n;i++)
	{
		scanf("%s",str[i]+1);
		for(j=1;j<=len;j++)
			val[i]=val[i]*seed+str[i][j];
		Insert(i);
	}
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d%d",&x,&a,&y,&b);
		if(x==y)
		{
			del(x);
			swap(str[x][a],str[x][b]);
			for(j=1,val[x]=0;j<=len;j++)
				val[x]=val[x]*seed+str[x][j];
			Insert(x);
			continue;
		}
		del(x),del(y);
		swap(str[x][a],str[y][b]);
		for(j=1,val[x]=val[y]=0;j<=len;j++)
			val[x]=val[x]*seed+str[x][j],
			val[y]=val[y]*seed+str[y][j];
		Insert(x),Insert(y);
	}
	Down(root);
	for(i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}



bzoj-1125 Poc

标签:bzoj   poi   splay   hash   

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

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