bzoj 4523 [Cqoi2016]路由表

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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值