cogimyunの小窝

Loading...

Luogu P7475 「C.E.L.U-02」简易输入法 题解

考虑到我们需要对于每次查询 \(S\),找到一个集合 \(T=\{S_i\in U|S\in pref(S_i)\}\),其中 \(pref(S)\) 表示字符串 \(S\) 的所有前缀的集合,我们必然可以使用 Trie 树维护,对于每个串 \(S\)\(S_{|S|-1}\) 在 Trie 树上对应节点 \(k\),那么节点 \(k\) 的子树即为我们要求的集合 \(T\),然而我们还同时需要维护第 \(x\) 大,所以我们不妨在 Trie 树的每个节点上维护一个平衡树,以维护节点子树内所有串的顺序,时间复杂度是 \(O(\sum|str|\log n+m|str|\log n)\) 的,空间复杂度为 \(O(\sum|str|+m|str|)\)

CODE

#include<bits/stdc++.h>
using namespace std;
mt19937 wqm(20100620);
struct treap{
    int l,r,sz,pri;
    pair<int,string> val;
}tr[2000005];
stack<int> q;
int cnt,n,m,cnt1;
struct node{
    int son[26],rt;
}t[500005];
bool operator<=(pair<int,string> x,pair<int,string> y){
    return (x.first==y.first)?x.second<=y.second:x.first>y.first;
}
void split(int p,int &l,int &r,pair<int,string> x){
    if(!p){l=r=0;return;}
    if(tr[p].val<=x){
        l=p;
        split(tr[p].r,tr[p].r,r,x);
    }
    else{
        r=p;
        split(tr[p].l,l,tr[p].l,x);
    }
    tr[p].sz=tr[tr[p].l].sz+tr[tr[p].r].sz+1;
}
int merge(int u,int v){
    if(!u||!v)return u|v;
    if(tr[u].pri>tr[v].pri){
        tr[u].r=merge(tr[u].r,v);
        tr[u].sz=tr[tr[u].l].sz+tr[tr[u].r].sz+1;
        return u;
    }
    tr[v].l=merge(u,tr[v].l);
    tr[v].sz=tr[tr[v].l].sz+tr[tr[v].r].sz+1;
    return v;
}
void insert_treap(int &rt,pair<int,string> x){
    int l,r,p;
    split(rt,l,r,x);
    if(!q.empty())p=q.top(),q.pop();
    else p=++cnt;
    tr[p].pri=wqm();
    tr[p].val=x;
    tr[p].sz=1;
    rt=merge(l,merge(p,r));
}
void insert(string s){
    int p=0;
    for(auto i:s){
        if(!t[p].son[i-'a']){p=t[p].son[i-'a']=++cnt1;t[p].rt=++cnt;tr[cnt].pri=wqm();tr[cnt].sz=1;tr[cnt].val={0,s};}
        else{p=t[p].son[i-'a'];insert_treap(t[p].rt,{0,s});}
    }
}
int find(string s){
    int p=0;
    for(auto i:s){
        p=t[p].son[i-'a'];
        if(!p)return p;
    }
    return p;
}
auto Rank(int p,int x){
    if(x==tr[tr[p].l].sz+1)return tr[p].val;
    if(x>tr[tr[p].l].sz+1)return(tr[p].r)?Rank(tr[p].r,x-1-tr[tr[p].l].sz):tr[p].val;
    return Rank(tr[p].l,x);
}
void instead_treap(int &rt,pair<int,string> x){
    int l,r,p;
    split(rt,l,r,x);
    auto y=x;
    y.second[y.second.size()-1]--;
    split(l,l,p,y);
    if(p)tr[p].l=r=0,q.push(p);
    insert_treap(l,{x.first+1,x.second});
    rt=merge(l,r);
}
void instead(pair<int,string> x){
    int p=0;
    for(auto i:x.second){
        p=t[p].son[i-'a'];
        instead_treap(t[p].rt,x);
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){string s;cin>>s;insert(s);}
    cin>>m;
    for(int i=1;i<=m;i++){
        string s;
        int x;
        cin>>s>>x;
        int y=find(s);
        if(!y)cout<<"404Error\n";
        auto z=Rank(t[y].rt,x);
        cout<<z.second<<endl;
        instead(z);
    }
    return 0;
}
posted @ 2026-01-08 07:26  cogimyun  阅读(1)  评论(0)    收藏  举报