HDU 4760 字典树(题意比较难理解)

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

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

//#pragma comment(linker, "/STACK:102400000")
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define pb push_back
#define mp make_pair
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 109
using namespace std;
int m,n,T,t;
char str[10];
int ch[800000][2],sz,id,len,ncase;
vector<int> g[800000];
int vis[1125],f[1125];
void init()
{
    sz=1;
    memset(ch[0],0,sizeof(ch[0]));
}
LL readip()
{
    int a,b,c,d;
    scanf("%d.%d.%d.%d",&a,&b,&c,&d);
    LL ans=0;
    ans+=a;ans<<=8;
    ans+=b;ans<<=8;
    ans+=c;ans<<=8;
    ans+=d;
    return ans;
}
void insert(LL ip,int len,int id)
{
    int u=0;
    for(int i=31,j=0;j<len;j++,i--)
    {
        int c=(ip>>i)&1;
        if(ch[u][c]==0)
        {
            ch[u][c]=sz++;
        }
        u=ch[u][c];
    }
    g[u].push_back(id);
}
void fun(LL ip)
{
    int u=0;
    for(int i=31;i>=0;i--)
    {
        int c=(ip>>i)&1;
        if(ch[u][c]==0)
        {
            break;
        }
        u=ch[u][c];
        for(int j=0;j<g[u].size();j++)
        if(vis[g[u][j]])
        f[g[u][j]]=ncase;
    }
}
int solve(LL ip)
{
    int u=0;
    for(int i=31;i>=0;i--)
    {
        int c=(ip>>i)&1;
        if(ch[u][c]==0)
        {
            break;
        }
        u=ch[u][c];
        for(int j=0;j<g[u].size();j++)
        if(vis[g[u][j]]&&f[g[u][j]]==ncase)
        return 1;
    }
    return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    init();
    while(scanf("%s",str)==1)
    {
        if(str[0]=='E')
        {
            scanf("%d%d",&id,&n);
            vis[id]=1;
            for (int i=0;i<n;++i )
            {
                LL ip=readip();
                scanf("/%d",&len);
                insert(ip,len,id);
            }
        }
        else if(str[0]=='D')
        {
            scanf("%d",&id);
            vis[id]=0;
        }
        else
        {
            ncase++;
            LL ip1=readip();
            LL ip2=readip();
            fun(ip1);
            puts(solve(ip2)?"F":"D");
        }
    }
    return 0;
}
View Code

 

posted @ 2013-10-11 18:23  baoff  阅读(283)  评论(0编辑  收藏  举报