题意:
给出一些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");
}
}