【Trie】[CQOI2016]路由表
题目描述
对于一次查询的一种理解方式是:无视其它所有查询操作,只看添加操作。先清空路由表,然后执行第1到a-1次添加操作。之后再执行第a到b次添加操作过程中,统计匹配改变的次数。
数据范围:
设一条表项的掩码长度为L,数据保证将目的地址转为二进制串后,末尾的32-L位均为0。
分析
在线地,每次在添加表项至路由表的时候,将该地址加入trie,然后在结束的节点标记上添加这个表项的时间。
对于每次询问,在trie上暴力匹配,然后用一个单调栈,使得能够匹配的表项出现的时间随着长度的增加而增加,最后通过二分查找找到在a,b之间改变了多少次即可。
代码
#include<cstdio>
#include<algorithm>
#define MAXN 1000000
#define INF 0xffffffffu
using 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();
}