【39.68%】【CF 714 C】Filya and Homework
【题解】
给你一个01串。从右到左对应了每个位置上的要求:0该位置为偶数。1该位置为奇数.
如果01串和要判断的数字不一样。谁短谁前面就补0;
我们不管谁短。直接在输入的数字前面补0至18位就好。
然后用字典树来操作。
插入数字的时候。不要具体记录这个数字是什么(没用!),只要知道这个数字是奇数还是偶数就行了嘛。所以93432你就记录11010.
不要被惯性思维影响!
直接记录数字会T!
然后字典树的域要记录以这个节点为终点的数字个数。
每次到这个节点累加这个就可以了。
【代码】
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_SIZE = 2000000;
int t;
int tree[MAX_SIZE][2] = { 0 },totn = 0,ans = 0;
int e[MAX_SIZE] = { 0 }, stop[MAX_SIZE] = { 0 };
char op[5], dig[30];
void insert()
{
int temp = 0;
int len = 18;
for (int i = len-1; i >=0; i--)
{
int d = dig[i] - '0';
d = d % 2;//直接记录是奇数还是偶数就可以了。
if (tree[temp][d] == 0)
tree[temp][d] = ++totn;
temp = tree[temp][d];
stop[temp]++;
}
e[temp]++;
}
void de_lete()
{
int temp = 0;
int len = 18;
for (int i = len-1; i >=0; i--)
{
int d = dig[i] - '0';
d = d % 2;
temp = tree[temp][d];
stop[temp]--;
}
e[temp]--;
}
void dfs(int rt, int len) //用dfs来累加答案。
{
ans += e[rt];
if (len < 0)
return;
int d = dig[len] - '0';
if (tree[rt][d])
dfs(tree[rt][d], len - 1);
}
void get_ans()
{
int temp = 0;
int len = 18;
dfs(temp, len - 1);
}
void input_data()
{
scanf("%d", &t);
char s1[30];
for (int i = 1; i <= t; i++)
{
scanf("%s%s", op, s1);
int len = strlen(s1);
for (int i = 0; i <= 18 - len - 1; i++)//补零
dig[i] = '0';
dig[18 - len] = '\0';
strcat(dig, s1);//最后dig记录的是补0后的字符
if (op[0] == '+')
insert();
else
if (op[0] == '-')
de_lete();
else
{
ans = 0;
get_ans();
printf("%d\n", ans);
}
}
}
int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
return 0;
}

浙公网安备 33010602011771号