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

bzoj-3261 最大异或和

时间:2015-07-25 18:35:02      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:bzoj   trie树   可持久化trie树   贪心   

题意:

给出一个长度为n的初始序列,和m次操作;

A操作:在序列后面加入一个数;

Q操作:给出一段区间[l,r]和一个数x,求区间中的p使p的后缀异或和与x的异或值最大;

n,m<=300000;


题解:

可持久化数据结构(2/4)进行中... ...

先做一个转化,因为是在序列后面加数,维护后缀和并不容易;

但是由于异或性质可以转化成前缀和的问题;

也就是在区间中选一个数,使其与另一个数的异或值最大;

这显然是一个trie树的经典问题,但是这里涉及到了区间问题;

那么如果对每个区间搞棵trie树就解决了;

之后上可持久化就结束了,记录trie树上每个结点被经历的次数,以记录这个结点是否在区间内;

询问时下标似乎需要一点特判,处理的有点恶心了但是不太影响吧;

复杂度O(25(n+m));


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 610000
using namespace std;
struct node
{
	int next[2],sum;
}a[N*30];
int root[N],tot;
char str[10];
void Insert(int x,int &p,int d)
{
	a[++tot]=a[p];
	p=tot;
	a[p].sum++;
	if(d==-1)	return ;
	Insert(x,a[p].next[(x&1<<d)?1:0],d-1);
}
int query(int nol,int nor,int x,int d)
{
	if(d==-1)	return 0;
	bool index=x&(1<<d)?1:0;
	if(a[a[nor].next[!index]].sum>a[a[nol].next[!index]].sum)
		return 1<<d|query(a[nol].next[!index],a[nor].next[!index],x,d-1);
	else
		return query(a[nol].next[index],a[nor].next[index],x,d-1);
}
int main()
{
	int n,m,i,j,k,l,r,x,all;
	scanf("%d%d",&n,&m);
	for(i=1,all=0;i<=n;i++)
	{
		scanf("%d",&x);
 		all^=x;
		root[i]=root[i-1];
		Insert(all,root[i],25);
	}
	for(i=1;i<=m;i++)
	{
		scanf("%s",str);
		if(str[0]=='A')
		{
			scanf("%d",&x);
			all^=x;
			root[n+1]=root[n];
			Insert(all,root[++n],25);
		}
		else
		{
			scanf("%d%d%d",&l,&r,&x);
			x=x^all;
			if(r==1)
			printf("%d\n",x);
			else if(l==1)
			printf("%d\n",max(x,query(root[0],root[r-1],x,25)));
			else
			printf("%d\n",query(root[l-2],root[r-1],x,25));
		}
	}
	return 0;
}




bzoj-3261 最大异或和

标签:bzoj   trie树   可持久化trie树   贪心   

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

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