HDU 6579 Operation

HDU题面

Time limit 4000 ms

Memory limit 262144 kB

OS Windows

Source 2019 Multi-University Training Contest 1

中文题意

一个序列支持两种操作——

  • 在后面插入一个数字,并使序列长度增加1
  • 询问某个区间的异或最大值

强制在线。

解题思路

基本就是上一道题Ivan and Burgers吧。上一道题我用的解法是在线的。虽然还是不会证明。

  • [x] CodeForces 1100F Ivan and Burgers 单纯询问区间异或最大值
  • [x] HDU 6579 Operation 多了个末尾插入数据的操作,还有强制在线
  • [ ] BZOJ 4184 shallot 这题还多了插入和删除的操作。居然是权限题……本地测一下算了。
  • [ ] UVALive 8514 XOR 2017ICPC西安的一道题,操作都差不多

另外洛谷P4735最大异或和跟这题长得有点像,但那个是可持久化trie。留坑

源代码

#include<cstdio>
#include<cstring>
#include<algorithm>

const int MAXN=1e6+5;
const int wide=31;

int T;
int n,m;

int p[MAXN][wide+2],pos[MAXN][wide+2];

void insert(int loc,int val)//location value
{
	for(int i=wide;~i;i--)
	{
		p[loc][i]=p[loc-1][i];
		pos[loc][i]=pos[loc-1][i];
	}
	int temp=loc;
	for(int i=wide;~i;i--)
	{
		if((val>>i)&1)
		{
			if(!p[loc][i])
			{
				p[loc][i]=val;
				pos[loc][i]=temp;
				return;
			}
			if(pos[loc][i]<temp)//还是不太懂
			{
				std::swap(pos[loc][i],temp);
				std::swap(p[loc][i],val);
			}
			val^=p[loc][i];
		}
	}
}


int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		memset(pos,0,sizeof(int)*(wide+2)*(n+2));
		memset(p,0,sizeof(int)*(wide+2)*(n+2));
		for(int i=1,v;i<=n;i++)
		{
			scanf("%d",&v);
			insert(i,v);
		}
		int lastans=0;
		while(m--)
		{
			int opt,l,r;
			scanf("%d",&opt);
			if(opt)
			{
				scanf("%d",&l);
				l^=lastans;
				insert(++n,l);
			}
			else
			{
				scanf("%d%d",&l,&r);
				l=(l^lastans)%n+1;
				r=(r^lastans)%n+1;
				if(l>r) std::swap(l,r);
				int ans=0;
				for(int i=wide;~i;i--)
				{
					if((ans^p[r][i])>ans&&pos[r][i]>=l)
						ans^=p[r][i];
				}
				printf("%d
",lastans=ans);
			}
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/wawcac-blog/p/11326542.html