读入稍微有点麻烦。。
BZOJ的大数据好评233。
原来的样例是:
11
A 0.0.0.0/8
Q 1.2.3.4 1 1
A 1.0.0.0/9
A 1.128.0.0/10
A 1.0.0.0/10
A 1.0.0.0/8
Q 1.2.3.4 1 5
A 1.2.0.0/16
A 1.2.3.1/32
Q 1.2.3.4 5 7
Q 1.2.3.1 5 7
很显然是字典树了吧。
对于每个A,转换为二进制串后截取前缀l插入字典树,在终态上标记插入时间。
然后每个Q,转换为二进制串后沿着字典树走,把碰到的终态搞出来模拟即可。
看了别人读入感觉自己写的好丑QwQ
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000005;
int ch[N][2], de[32], pos[N], rt = 1, cnt = 1;
void decode(const char *s) {
int p[4], i, j, k;
sscanf(s, "%d.%d.%d.%d", p, p + 1, p + 2, p + 3);
for (i = k = 0; i < 4; ++i)
for (j = 7; j >= 0; --j)
de[k++] = (p[i] >> j) & 1;
}
void insert(int *s, int l, int id) {
int p = rt, i;
for (i = 0; i < l; ++i) {
if (!ch[p][s[i]])
ch[p][s[i]] = ++cnt;
p = ch[p][s[i]];
}
pos[p] = id;
}
pair<int, int> a[N];
int query(int *s, int l, int r) {
int p = rt, i, m = -1, ans = 0, n = 0;
for (i = 0; i < 32; ++i) {
if (!ch[p][s[i]])
break;
p = ch[p][s[i]];
if (pos[p] && pos[p] <= r)
a[n++] = make_pair(pos[p], i + 1);
}
sort(a, a + n);
for (i = 0; i < n; ++i)
if (m < a[i].second) {
m = a[i].second;
if (a[i].first >= l) ++ans;
}
return ans;
}
int main() {
char s[32], op[2];
int t, l, a, b, id = 0;
scanf("%d", &t);
while (t--) {
scanf("%s", op);
if (op[0] == 'A') {
scanf("%[^/]/%d", s, &l);
decode(s); insert(de, l, ++id);
} else {
scanf("%s%d%d", s, &a, &b);
decode(s); printf("%d\n", query(de, a, b));
}
}
return 0;
}