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;
}

浙公网安备 33010602011771号