BZOJ 4523 CQOI 2016 路由表 字典树

读入稍微有点麻烦。。
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;
}

你可能感兴趣的:(trie,字典树,bzoj,CQOI,省选)