题目描述
一台密码机按照以下的方式产生密码:首先往机器中输入一系列数,然后取出其中一部分数,将它们异或以后得到一个新数作为密码。现在请你模拟这样一台密码机的运行情况,用户通过输入控制命令来产生密码。密码机中存放了一个数列,初始时为空。密码机的控制命令共有3种:
ADD
把到数列的最后。
REMOVE
在数列中找出第一个等于的数,把它从数列中删除。
XOR BETWEEN AND
对于数列中所有大于等于并且小于等于的数依次进行异或,输出最后结果作为密码。如果只有一个数满足条件,输出这个数。如果没有任何数满足条件,输出0。
你可以假设用户不会REMOVE一个不存在于数列中的数,并且所有输入的数都不超过20000。
数据范围
输入数字小于20000,操作小于60000
样例输入
ADD 5
ADD 6
XOR BETWEEN 1 AND 10
REMOVE 5
XOR BETWEEN 6 AND 8
样例输出
3
6
解题思路
大水题,不写解题思路了233.
建一棵线段树,维护区间内的异或和,至于添加和删除,其实并没有什么区别=-=。
代码
#include <bits/stdc++.h>
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
struct node{
int L,r,val;
}Tree[80005];
void Build(int v,int L,int r){
Tree[v]=(node){L,r,0};
if(L==r)return;
Build(2*v,L,(L+r)/2);
Build(2*v+1,(L+r)/2+1,r);
}
void Insert(int v,int pos){
Tree[v].val^=pos;
if(Tree[v].L==Tree[v].r)return;
if(pos<=(Tree[v].L+Tree[v].r)/2)Insert(2*v,pos);
else Insert(2*v+1,pos);
}
int Ask(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return 0;
if(L<=Tree[v].L&&Tree[v].r<=r)return Tree[v].val;
return Ask(2*v,L,r)^Ask(2*v+1,L,r);
}
int main(){
char s[66];
Build(1,0,20001);
while(scanf("%s",s)!=EOF){
string ss=s;
if(ss=="ADD"||ss=="REMOVE")Insert(1,Getint());
else {
int L=Getint(),r=Getint();
cout<<Ask(1,L,r)<<"\n";
}
}
return 0;
}