713A:Sonya and Queries
题意简述
维护一个可重集合,有三种操作。
操作总数
n
1.添加
2.删除
ai
。
3.询问当前集合中,对于
ai
十进制的每一位,集合中有多少元素的奇偶性和
ai
相同。比较时位数较少的从左边补
0
。
数据范围
1≤n≤105
思路
维护两棵Trie树。
一棵维护添加,一棵维护删除。
询问就是两棵Trie树答案的差。
sprintf非常好用。
代码
#include<cstdio>
using namespace std;
namespace Trie
{
struct Node{
Node *next[2];
int val;
Node();
}*null;
Node::Node()
{
next[0]=next[1]=null;
val=0;
}
Node pool[1800010];
Node *Root[2];
int poolt;
Node *NewNode()
{
pool[poolt]=Node();
return &pool[poolt++];
}
void Init()
{
null=NewNode();
*null=Node();
Root[0]=NewNode();
Root[1]=NewNode();
}
void insert(char *tmp,int ty)
{
Node *k=Root[ty];
int x;
for (int i=17;i>=0;i--)
{
x=(tmp[i]-'0')%2;
if (k->next[x]==null)
k->next[x]=NewNode();
k=k->next[x];
}
k->val++;
}
int query(char *tmp)
{
Node *k=Root[0];
int x,ret=0;
for (int i=17;i>=0;i--)
{
x=(tmp[i]-'0')%2;
if (k->next[x]==null)
break;
k=k->next[x];
}
ret+=k->val;
k=Root[1];
for (int i=17;i>=0;i--)
{
x=(tmp[i]-'0')%2;
if (k->next[x]==null)
break;
k=k->next[x];
}
ret-=k->val;
return ret;
}
}
char getopt()
{
char ch=getchar();
while (ch!='+'&&ch!='-'&&ch!='?')
ch=getchar();
return ch;
}
char opt,tmp[20];
long long u;
int n;
int main()
{
Trie::Init();
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
opt=getopt();
scanf("%I64d",&u);
sprintf(tmp,"%018I64d",u);
if (opt=='+')
Trie::insert(tmp,0);
if (opt=='-')
Trie::insert(tmp,1);
if (opt=='?')
printf("%d\n",Trie::query(tmp));
}
return 0;
}