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; }