P5768

P5768 [CQOI2016]路由表

对于每个字符串,将其转换成二进制串的形式,每 \(8\) 位表示一个数,且每个串都有一个长度数值 \(L_i\),表示需匹配的位数。

给定 \(n\) 次操作, 操作有两种:

  • 插入操作:添加题目给出的掩码长度为 \(L_i\) 的串 \(S\)
  • 查询操作:询问给出的串 \(S\)\(\left[ L,R \right]\) 次插入操作时的字符串匹配时匹配情况变化了几次

很明显可以用 01trie 维护。

对于每个添加的操作,就将其拆分为 01 串的形式插入 01trie 即可。

至于查询的操作,题目直接明说了用差分,即 \(\left[L,R \right]\) 可以通过 \(\left[1,R \right]-\left[1,L \right]\) 求出。

稍加思考可知匹配的过程能类比单调栈的操作。

就是在 01trie 树上查询时维护一个单调栈:

  • 如果当前标记在范围之内,就将栈顶所有时间更晚的标记弹出,再将当前节点入栈。
  • 最后结果就是单调栈中的元素个数。
#include <bits/stdc++.h>
using namespace std;const int N=3e6;
int R(){
    int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);return x;
}void W(int x){if(x>9)W(x/10);putchar(x%10+'0');}
int n,t[N][2],u,c,len,l,r,p[N],tot,f[N],cnt,mi,x,sum,g;char o;
void ip(){for(int j=0,k;j<4;++j){k=R();for(int v=7;v>=0;v--)p[j*8+v]=k%2,k>>=1;}return ;}
void in(){u=0;for(int i=0;i<len;i++){if(!t[u][p[i]])t[u][p[i]]=++tot;u=t[u][p[i]];}f[u]=++cnt;}
int q(int x){
    u=0;stack <int> s;
    for(int i=0;i<32;i++){
        if(!t[u][p[i]])break;u=t[u][p[i]];
        if(f[u]&&f[u]<=x){g=f[u];while(s.size()&&g<s.top())s.pop();s.push(g);}
    }return s.size();
}int main(){
    n=R();for(int i=1;i<=n;i++){
        cin>>o;ip();
        if(o=='A')len=R(),in();
        else l=R(),r=R(),W(q(r)-q(l-1)),puts("");
    }return 0;
}
posted @ 2022-04-02 16:44  AIskeleton  阅读(28)  评论(0编辑  收藏  举报