Codeforces Round #371 (Div. 2) - C

 

题目链接:http://codeforces.com/contest/714/problem/C

题意:给定t个操作。维护一个可重复集合。操作分为3种:  + num:向集合中插入数num; - num:从集合中删除数num; ? string(01串):查询集合有多少个数满足和01串匹配。  匹配规则:把集合中的数的转化为以每一位的奇偶性组成的01串,然后匹配时如果string长度比集合中的数小时,在string前面补0. 如果集合中的数的长度比string短时,在数的前面补0。

思路;因为有插入删除和匹配。而且是01串。所以我们可以构造一棵01字典树来存集合中的数字。 插入对应字典树插入。删除对应字典树值-1.匹配查询则稍微对string做下处理。定义pos为string从左到右第一个'1'的下标(不存在则为-1)。然后匹配时逆序匹配,当匹配到pos位置时,当前字典树的子树的根为x。则一直沿着x的'0'子树下去,然后统计结点上的贡献。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<time.h>
#include<cmath>
#include<set>
using namespace std;
typedef long long int LL;
const int MAXN = 1000000 + 5;
struct Trie{
    int val;
    int child[2];
    Trie(){
        val = 0;
        memset(child, 0, sizeof(child));
    }
}trie[MAXN];
int trieN;
void Insert(char *str){
    int d, x = 0;
    for (int i = strlen(str)-1; i >= 0;i--){
        d = (str[i] - '0') % 2;
        if (trie[x].child[d] == 0){
            trie[x].child[d] = ++trieN;
        }
        x = trie[x].child[d];
    }
    trie[x].val++;
}
int Search(char *str){
    int d, x = 0,cnt=0,pos=-1;
    for (int i = 0; str[i]; i++){
        if (str[i] == '1'){
            pos = i; break;
        }
    }
    if (pos != -1){
        for (int i = strlen(str) - 1; i >= 0; i--){
            d = (str[i] - '0') % 2;
            if (trie[x].child[d] == 0){ return 0; }
            x = trie[x].child[d];
            if (i == pos){ break; } //之后的string都是0
        }
    }
    cnt += trie[x].val;
    while ((x = trie[x].child[0])!=0){ //沿着当前的子树根一直往'0'子树走
        cnt += trie[x].val;
    }
    return cnt;
}
void Delete(char *str){
    int x = 0, d;
    for (int i = strlen(str) - 1; i >= 0; i--){
        d = (str[i] - '0') % 2;
        if (trie[x].child[d] == 0){
            return;
        }
        x = trie[x].child[d];
    }
    trie[x].val == 0 ? trie[x].val = 0 : trie[x].val--;
}
int main(){
#ifdef kirito
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int n; char op[2], num[20];
    while (~scanf("%d", &n)){
        trieN = 0;
        for (int i = 0; i < n; i++){
            scanf("%s %s", op, num);
            switch (op[0]){
            case '+':
                Insert(num);
                break;
            case '-':
                Delete(num);
                break;
            default:
                printf("%d\n",Search(num));
            }
        }
    }
    return 0;
}

 

posted @ 2016-09-14 17:08  キリト  阅读(156)  评论(0编辑  收藏  举报