hdu4760 字典树 (2013网络赛)

网络知识比较差,造成看题非常吃力

题目大意:有多个政策,每个政策里面有很多子网,E 表示加入一个政策,D表示禁止一个政策,F就是询问ip1,ip2是不是在同一个政策中。

思路:子网有个特点前缀相同,对于E操作,不难想到用字典树来维护所有子网(即ip的前缀),每个节点用一个vector保存该子网(即前缀)所属于的所有政策的标号。对于D操作,我们用一个数组维护该政策可不可用,对于F就是先把ip1所在的政策做一下标记,然后让ip2所在的政策有没有在这些标记中的即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 33005;
typedef long long ll;
int Q;
bool vis[1055];
int mark[1055];

int ch[maxn][2], n = 1;
vector <int> val[maxn];
void insert(ll ip, int len, int id) {
    int p = 0;
    for(int i = 31; i >= 32 - len; i--) {
        int k = (ip >> i) & 1;
        if(!ch[p][k])
            ch[p][k] = n++;
        p = ch[p][k];
    }
    val[p].push_back(id);
}
void color(ll ip) {
    int p = 0;
    for(int i = 31; i >= 0; i--) {
        int k = (ip >> i) & 1;
        if(!ch[p][k]) return;
        p = ch[p][k];
        for(int j = 0; j < val[p].size(); j++)
            if(vis[val[p][j]])
                mark[val[p][j]] = Q;
    }
}
bool judge(ll ip) {
    int p = 0;
    for(int i = 31; i >= 0; i--) {
        int k = (ip >> i) & 1;
        if(!ch[p][k]) return false;
        p = ch[p][k];
        for(int j = 0; j < val[p].size(); j++) {
            if(mark[val[p][j]] == Q)
                return true;
        }
    }
    return false;
}

ll getIp(int a, int b, int c, int d) {
    ll ret = 0;
    ret |= (ll) a << 24;
    ret |= (ll) b << 16;
    ret |= (ll) c << 8;
    ret |= d;
    return ret;
}

char op[3];
int a, b, c, d, e, id;
int main() {
    while(~scanf("%s", op)) {
        if(op[0] == 'E') {
            int n;
            scanf("%d%d", &id, &n);
            while(n--) {
                scanf("%d.%d.%d.%d/%d", &a, &b, &c, &d, &e);
                insert(getIp(a, b, c, d), e, id);
            }
            vis[id] = 1;
        }
        if(op[0] == 'D') {
            scanf("%d", &id);
            vis[id] = 0;
        }
        if(op[0] == 'F') {
            Q++;
            scanf("%d.%d.%d.%d", &a, &b, &c, &d);
            color(getIp(a, b, c, d));
            scanf("%d.%d.%d.%d", &a, &b, &c, &d);
            puts( judge(getIp(a, b, c, d))? "F" : "D");
        }
    }
    return 0;
}


你可能感兴趣的:(hdu4760 字典树 (2013网络赛))