http://codeforces.com/contest/714/problem/C
题目大意:有t个询问,每个询问有三种操作
①加入一个数值为a[i]的数字
②消除一个数值为a[i]的数字
③给一个字符串s,s中分别表示0和1,0表示目前该位为偶数,1表示目前该位为奇数。然后询问目前数组中和s每一位能匹配的个数。如果数组中目前的该数字比s的len要短,那么我们就在s的左边一直加0。如果数组中的目前的数字比s的len长,那么就在该数组的左边一直加0就好了。问能和s匹配的有几个,并输出
思路:我是用map来标记奇偶的,因为有前导0,所以我们把0的val都改成2,首先dfs出所有的情况,并每次给他标上一个ID,然后每次询问的时候找ID就好了。
貌似看到别人用的是trie树来做。。。

//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha; printf("haha "); const int maxn = 1e6 + 5; int dfsclock; map<LL, int> ID; LL cnt[maxn], cnt2[maxn]; LL cal(LL x, int n){ LL res = 1; while (n){ if (n & 1) res = res * x; x = x * x; n >>= 1; } return res; } void dfs(LL val, int cell){ if (cell == 18) return ; LL add = cal(10LL, cell); for (LL i = 1; i <= 2; i++){ ID[val + add * i] = ++dfsclock; dfs(val + add * i, cell + 1); } } ///1~18位,变成0~17位 int main(){ dfs(0LL, 0); ID[0] = ++dfsclock; int t; cin >> t; char ch[18]; for (int i = 0; i < t; i++){ char s[2]; scanf("%s %s", s, ch); int len = strlen(ch); LL val = 0; if (s[0] == '+') { for (int j = len - 1; j >= 0; j--){ ch[j] -= '0'; if (ch[j] % 2 == 0) { val += 2 * cal(10LL, len - 1 - j); } else { val += 1 * cal(10LL, len - 1 - j); } cnt[ID[val]]++; } for (int i = len; i <= 17; i++){///扩张到18位的 val += 2 * cal(10LL, i); cnt[ID[val]]++; } } else if (s[0] == '-'){ for (int j = len - 1; j >= 0; j--){ ch[j] -= '0'; if (ch[j] % 2 == 0) { val += 2 * cal(10LL, len - 1 - j); } else { val += 1 * cal(10LL, len - 1 - j); } cnt[ID[val]]--; } for (int i = len; i <= 17; i++){ val += 2 * cal(10LL, i); cnt[ID[val]]--; } } else if (s[0] == '?'){ LL ans = 0; int pos = 0; for (int i = 0; i <= len - 1; i++){ if (ch[i] != '0') { pos = i; break; } } for (int i = len - 1; i >= 0; i--){ if (ch[i] == '0') val += 2 * cal(10LL, len - 1 - i); else val += 1 * cal(10LL, len - 1 - i); } ans += cnt[ID[val]]; for (int i = len; i <= 17; i++){ LL tmp = 2 * cal(10LL, i); ans += cnt[ID[val + tmp]] - cnt[ID[val]];///每次增加的匹配数一定是在前一个集合里面没有出现过的 val += tmp; } printf("%I64d ", ans); } } return 0; }