Bzoj 1499
Bzoj 1808

Bzoj 2741

coc youyl posted @ 2015年6月27日 21:56 in bzoj , 670 阅读

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2741

题目分类:可持久化数据结构,分块

题意:

给出一个序列,求区间内最大异或和子串,强制在线。

题解:

使用可持久化字典树支持查询对于一个端点和一个区间的最大异或和子串。

然后分块,考虑记录每个块的开头到任意一个位置的询问结果,这样就可以根号下时间处理。

程序:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int ins[60];
inline void despose(int x)
{
	for (int i=1;i<=31;i++)
	{
		if(((1<<(i-1))&x)!=0)ins[i]=1;
		else ins[i]=0;
	}
}
struct functionaltrie
{
	int siz,st[3300000],chi[3300000][2],val[3300000];
	functionaltrie()
	{
		siz=1;
		st[0]=1;
	}
	inline void insertinit()
	{
		int tmp=1;
		for (int i=31;i>=1;i--)
		{
		//	printf("%d %d %d\n",i,ins[i],tmp);
			if(chi[tmp][ins[i]]==0)
			{
				siz++;
				chi[tmp][ins[i]]=siz;
			}
			tmp=chi[tmp][ins[i]];
		}
	}
	inline void insert(int x)
	{
		siz++;
		st[x]=siz;
		int tmp=siz,tmf=st[x-1];
		for (int i=31;i>=1;i--)
		{
		//	printf("%d %d %d\n",i,ins[i],tmp);
			siz++;
			chi[tmp][ins[i]]=siz;
			val[tmp]=1+val[tmf];
			chi[tmp][1-ins[i]]=chi[tmf][1-ins[i]];
			tmp=chi[tmp][ins[i]];
			tmf=chi[tmf][ins[i]];
		}
		val[tmp]=val[tmf]+1;
	}
	inline int query(int x,int y)
	{
		x++,y++;
		int tx=st[x],ty=st[y],ans=0;
	//	printf("--%d %d\n",x,y);
		for (int i=31;i>=1;i--)
		{  
		//	printf("--%d %d %d\n",tx,ty,ins[i]);
			if(val[chi[ty][1-ins[i]]]-val[chi[tx][1-ins[i]]]>0)
			{
				ans+=(1<<(i-1));
				tx=chi[tx][1-ins[i]];
				ty=chi[ty][1-ins[i]];	
			}
			else
			{
				tx=chi[tx][ins[i]];
				ty=chi[ty][ins[i]];
			}
		}return ans;
	}
}sgt;
int n,m,a[26000],len,par,x1,x2,lastans,num[26000],pos[26000],sta[26000],end[26000];
int pre[430][26000];
int main()
{
	scanf("%d %d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		a[i]=(a[i-1]^a[i]);
		despose(a[i]); 
		sgt.insertinit();
	}
	despose(0);
	sgt.insertinit();
	sgt.insert(1);
	for (int i=1;i<=n;i++)
	{
		despose(a[i]);
		sgt.insert(i+1);
	}
	len=(int)sqrt(n);par=1;
	sta[1]=1;
	for (int i=1;i<=n;i++)
	{
		num[i]=num[i-1]+1;
		sta[i]=par;
		if(num[i]>len)
		{
			end[par]=i-1;
			par++;
			sta[par]=i;
			num[i]-=len;
		}pos[i]=par;
	}
	end[par]=n;
	for (int i=1;i<=par;i++)
	{
		pre[i][sta[i]]=0;
		for (int j=sta[i]+1;j<=n;j++)
		{
			despose(a[j]);
			pre[i][j]=max(pre[i][j-1],sgt.query(sta[i]-2,j));
		//	printf("%d %d %d\n",i,j,pre[i][j]);
		}
	}
	sta[par+1]=n+1;
	for (int i=1;i<=m;i++)
	{
		scanf("%d %d",&x1,&x2);
		x1=((long long)x1+(long long)lastans)%(long long)n+1LL;
		x2=((long long)x2+(long long)lastans)%(long long)n+1LL;
		if(x1>x2)swap(x1,x2);
		int tp=pos[x1]+1;//printf("%d---%d\n",x1,x2);
		if(pos[x1]==pos[x2])
		{
			int ans=0;
			for (int j=x1-1;j<x2;j++)
			{
				despose(a[j]);
				ans=max(ans,sgt.query(x1-2,x2));
			}printf("%d\n",ans);lastans=ans;
		}
		else
		{
			int ans=pre[tp][x2];//printf("%d %d %d\n",tp,x2,ans);
			for (int j=x1-1;j<sta[tp];j++)
			{
				despose(a[j]);
				ans=max(ans,sgt.query(x1-2,x2));
			}printf("%d\n",ans);lastans=ans;
		}
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter