还以为要可持久化Trie
简单分析一下发现就是Trie+单调栈
查询的时候从根向下在Trie上走,每次找到当前节点上满足条件的最小时间点加到栈里去
栈中时间点为递增序
答案就是栈里元素的数量
(lower_bound好慢啊,是不是可以直接暴力啊)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
const int N=1000000+5;
int ch[N*32][2],sz,hash[N*32],tot;
vector<int>val[N];
int build(int u){
if(hash[u])return hash[u];
return hash[u]=++tot;
}
int find(int u){return hash[u];}
void insert(int *s,int n,int ti){
int u=0;
rep(i,1,n){
if(!ch[u][s[i]])ch[u][s[i]]=++sz;
u=ch[u][s[i]];
}
val[build(u)].push_back(ti);
}
int st[N],tp;
void push(int x){
while(tp&&x<st[tp])tp--;
st[++tp]=x;
}
int work(int *s,int n,int a){
int u=0,last=0;
rep(i,1,n){
if(!ch[u][s[i]])return last;
u=ch[u][s[i]];
if(find(u)&&val[find(u)][0]<a)last=i;
}
return last;
}
int solve(int *s,int n,int a,int b){
tp=0;
int u=0,l=work(s,n,a);
rep(i,1,n){
if(!ch[u][s[i]])break;
u=ch[u][s[i]];
if(i>l&&find(u)){
int v=find(u);
int k=lower_bound(val[v].begin(),val[v].end(),a)-val[v].begin();
if(k!=(int)val[v].size()&&val[v][k]<=b)
push(val[v][k]);
}
}
return tp;
}
int s[40];
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int n,m=0,a,b,c,d,l,r;scanf("%d",&n);
char opt[5];
rep(t,1,n){
scanf("%s",opt);
if(opt[0]=='A'){
scanf("%d.%d.%d.%d/%d",&a,&b,&c,&d,&l);
per(i,8,1)s[i]=a&1,a>>=1;
per(i,16,9)s[i]=b&1,b>>=1;
per(i,24,17)s[i]=c&1,c>>=1;
per(i,32,25)s[i]=d&1,d>>=1;
insert(s,l,++m);
}else{
scanf("%d.%d.%d.%d %d %d",&a,&b,&c,&d,&l,&r);
per(i,8,1)s[i]=a&1,a>>=1;
per(i,16,9)s[i]=b&1,b>>=1;
per(i,24,17)s[i]=c&1,c>>=1;
per(i,32,25)s[i]=d&1,d>>=1;
printf("%d\n",solve(s,32,l,r));
}
}
return 0;
}