[hoj 2278]IP Filtering[二分+区间合并]

来源:互联网 发布:cad软件官网 编辑:程序博客网 时间:2024/06/09 14:37

题意:

给出一些IP段,再给出一些IP,问这些IP是否在这些IP段中.

注意给出的段有可能左>右.要倒一下.


思路:

二分是已知值,找下标.在本题中是已知IP,找此IP应属于的段的下标.找到应属于的段的时候,判断是否在此段中即可.


/**     几个错误:IP左边为高位,右边为低位,这个不能任意改.             要用uint.修改要彻底.             区间合并的时候不仅考虑嵌套,还有重叠,相邻.**/#include <cstdio>#include <algorithm>using namespace std;typedef unsigned int uint;const int MAX = 1000005;const uint INF = ~0u;int cnt,n;typedef struct Seg{    uint l,r;}Seg;bool cmp(Seg a, Seg b){    return (a.l==b.l)?(a.r<b.r):(a.l<b.l);}Seg sg[MAX];void MergeSeg(){    n = cnt;    uint rmax = sg[0].r,il = 0;    for(int i=1;i<cnt;i++)    {        while(sg[i].l<=rmax+1 && i<cnt)        {            if(sg[i].r>rmax)    rmax = sg[i].r;            sg[i].l = sg[i].r = INF;            i++;            n--;        }        if(sg[i].l>rmax)        {            sg[il].r = rmax;            il = i;            rmax = sg[i].r;        }    }    sort(sg,sg+cnt,cmp);}bool bin(uint x){    int ans = -1,l = 0, r = n-1, mid;    while(l<=r)    {        mid = (l+r)>>1;        if(sg[mid].l > x)     r = mid - 1;        else if(sg[mid].l < x)        {            ans = mid;            l = mid + 1;        }        else        {            ans = mid;            break;        }    }    if(ans!=-1)    {        if(sg[ans].r>=x)    return true;    }    return false;}int main(){    uint a,b,c,d,x,y,z,w,i=0;    while(scanf("%u.%u.%u.%u %u.%u.%u.%u",&a,&b,&c,&d,&x,&y,&z,&w)==8)    {        uint p = a*(1<<24) + b*(1<<16) + c*(1<<8) + d;        uint q = x*(1<<24) + y*(1<<16) + z*(1<<8) + w;        if(p<=q)        {            sg[i].l = p;            sg[i++].r = q;        }        else        {            sg[i].l = q;            sg[i++].r = p;        }    }    cnt = i;    sort(sg,sg+cnt,cmp);    MergeSeg();    getchar();    while(scanf("%u.%u.%u.%u",&a,&b,&c,&d)==4)    {        uint tIP = a*(1<<24) + b*(1<<16) + c*(1<<8) + d;        if(bin(tIP))    puts("yes");        else    puts("no");    }}


原创粉丝点击