Trie树的运用。
对于A操作,将IP地址转为2进制串后插入Trie树中,在结束节点增加时间标记。
对于Q操作,将IP地址转为2进制串后在Trie树中匹配。
在匹配过程中,用单调栈维护时间单调递增。栈的大小就是答案。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long LL;
struct Trie{int ch[2],ti;}t[35000005];//memory?? 400MB
int bh=0,rt=0,tt=0,stk[2000005],xbj;
void Insert(int &x,LL num,int dep,int len)
{ if(!x){x=++bh;t[x]=t[0];}
if(!len){t[x].ti=tt;return;}//在结束节点打上时间标记
int p=int((num>>(dep-1))&1);
Insert(t[x].ch[p],num,dep-1,len-1);
}
int Query(int x,int L,int R,LL num,int dep)//随着匹配的进行,匹配长度在不断增加
{ if(t[x].ti)
{if(t[x].ti<L)stk[0]=0;//时间在询问区间之前,则清空栈
if(L<=t[x].ti&&t[x].ti<=R)//时间在询问区间中,则维护时间单调递增
{while(stk[0]&&stk[stk[0]]>t[x].ti)stk[0]--;
stk[++stk[0]]=t[x].ti;
}
}
if(!dep)return stk[0];
int p=int((num>>(dep-1))&1);
return Query(t[x].ch[p],L,R,num,dep-1);
}
int main()
{ int i,N,e,L,R,ans;
LL a,b,c,d;
char s[10];
t[0].ch[0]=t[0].ch[1]=t[0].ti=0;
scanf("%d",&N);
for(i=1;i<=N;i++)
{scanf("%s",s+1);
if(s[1]=='A')
{scanf("%lld.%lld.%lld.%lld/%d",&a,&b,&c,&d,&e);
tt++;
Insert(rt,(a<<24LL)+(b<<16LL)+(c<<8LL)+d,32,e);
}
else if(s[1]=='Q')
{scanf("%lld.%lld.%lld.%lld",&a,&b,&c,&d);
scanf("%d%d",&L,&R);
stk[0]=0;
printf("%d\n",Query(rt,L,R,(a<<24LL)+(b<<16LL)+(c<<8LL)+d,32));
}
}
return 0;
}