【Trie】[CQOI2016]路由表

来源:互联网 发布:会编程可以在家工作吗 编辑:程序博客网 时间:2024/05/16 16:12

题目描述

这里写图片描述
这里写图片描述

对于一次查询的一种理解方式是:无视其它所有查询操作,只看添加操作。先清空路由表,然后执行第1到a-1次添加操作。之后再执行第a到b次添加操作过程中,统计匹配改变的次数。

数据范围:
设一条表项的掩码长度为L,数据保证将目的地址转为二进制串后,末尾的32-L位均为0。

分析

在线地,每次在添加表项至路由表的时候,将该地址加入trie,然后在结束的节点标记上添加这个表项的时间。
对于每次询问,在trie上暴力匹配,然后用一个单调栈,使得能够匹配的表项出现的时间随着长度的增加而增加,最后通过二分查找找到在a,b之间改变了多少次即可。

代码

#include<cstdio>#include<algorithm>#define MAXN 1000000#define INF 0xffffffffuusing namespace std;typedef unsigned int uint;int n,cnt;struct query{    uint c;    int len;    inline query(){    }    inline query(uint c,int len):c(c),len(len){    }}q[MAXN+10];struct node{    int pos;    int ch[2];}tree[MAXN*32+10],*root=tree,*tcnt=tree;template<class T>void Read(T &x){    char c;    while(c=getchar(),c!=EOF)        if(c>='0'&&c<='9'){            x=c-'0';            while(c=getchar(),c>='0'&&c<='9')                x=x*10+c-'0';            ungetc(c,stdin);            return;        }}void read(){    Read(n);}void solve(){    char s[20];    uint c,t;    int len,i,a,b,best,ans;    while(n--){        scanf("%s",s);        if(s[0]=='A'){            c=a=0;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(len);            q[++cnt]=query(c,len);        }        else{            c=a=ans=0;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a),Read(b);            best=0;            for(i=1;i<a;i++){                t=INF^((1ll<<(32-q[i].len))-1);                if(q[i].c==(c&t))                    if(q[i].len>q[best].len)                        best=i;            }            for(;i<=b;i++){                t=INF^((1ll<<(32-q[i].len))-1);                if(q[i].c==(c&t))                    if(q[i].len>q[best].len)                        best=i,ans++;            }            printf("%d\n",ans);        }    }}int s[MAXN+10],tp;void solve2(){    char ss[20];    int a,b,len,i,x[40],pos,ans;    uint c;    bool d;    node *p;    while(n--){        scanf("%s",ss);        if(ss[0]=='A'){            c=0;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(a);            c=(c<<8)+a;            Read(len);            p=root;            for(i=31;i>=32-len;i--){                d=(c>>i)&1;                if(!p->ch[d])                    p->ch[d]=++tcnt-tree;                p=tree+p->ch[d];            }            p->pos=++cnt;        }        else{            len=0;            Read(a);            for(i=7;i>=0;i--)                x[++len]=(a>>i)&1;            Read(a);            for(i=7;i>=0;i--)                x[++len]=(a>>i)&1;            Read(a);            for(i=7;i>=0;i--)                x[++len]=(a>>i)&1;            Read(a);            for(i=7;i>=0;i--)                x[++len]=(a>>i)&1;            Read(a),Read(b);            tp=0;            p=root;            for(i=1;i<=32;i++){                if(p->ch[x[i]])                    p=tree+p->ch[x[i]];                else                    break;                if(p->pos&&p->pos<=b){                    pos=p->pos;                    while(tp>0&&s[tp]>pos)                        tp--;                    s[++tp]=pos;                }            }            ans=tp-(lower_bound(s+1,s+tp+1,a)-s)+1;            printf("%d\n",ans);        }    }}int main(){    read();    if(n<=1000)        solve();    else        solve2();}
0 0
原创粉丝点击