【树状数组】密码机(ZJOI2003)

Description

  一台密码机按照以下的方式产生密码:首先往机器中输入一系列数,然后取出其中一部分数,将它们异或以后得到一个新数作为密码。现在请你模拟这样一台密码机的运行情况,用户通过输入控制命令来产生密码。密码机中存放了一个数列,初始时为空。密码机的控制命令共有3种:

  ADD
    把放到数列的最后。
  REMOVE
    在数列中找出第一个等于的数,把它从数列中删除。
  XOR BETWEEN AND
    对于数列中所有大于等于并且小于等于的数依次进行异或,输出最后结果作为密码。如果只有一个数满足条件,输出这个数。如果没有任何数满足条件,输出0。

  你可以假设用户不会REMOVE一个不存在于数列中的数,并且所有输入的数都不超过20000。

Input

  包括了一系列的控制命令。每个控制命令占据单独一行。输入文件中没有多余的空行。文件不超过60000行。

Output

 对于每个XOR命令,依次输出一行包括你的密码机所产生的密码。输出文件中不应该包含任何的多余字符

Sample Input

ADD 5
ADD 6
XOR BETWEEN 1 AND 10
REMOVE 5
XOR BETWEEN 6 AND 8

Sample Output

3
6


思路

  • 异或具有aa=0,a0=a的性质

代码

#include <iostream>
#include <cstdio>
using namespace std;
char op[20];
int c[33000];
int lowbit(int x){return x&(-x);}
void add(int x,int d){for(int i=x;i<=33000;i+=lowbit(i)) c[i]^=d;}
int ask(int x)
{
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i)) ans^=c[i];
	return ans;
}
int main()
{
	while(~scanf("%s",&op))
	{
		if(op[0]=='A'||op[0]=='R')
		{
			int x; scanf("%d",&x);
			add(x,x);
		}
		else
		{
			int x,y; scanf("%s%d%s%d",&op,&x,&op,&y);
			if(x>y) puts("0");
			else printf("%d\n",ask(x-1)^ask(y));
		}
	}
	return 0;
}
posted @ 2020-08-03 17:33  wuwendongxi  阅读(187)  评论(0编辑  收藏  举报