Description
支持插入/删除人名,询问从哪一时刻开始以某一字符串为前缀的人名个数超过 \(k\) 。
\(1\leqslant q\leqslant 100000,1\leqslant len\leqslant 60\)
Solution
建 \(trie\) ,每个点开 \(vector\) 记录达到每个个数的时刻 \(k\) ,然后直接查,
Code
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
int n;
struct node
{
int tr[10];
}t[MAXN * 65];
int ptr = 0;
int newnode(){return ++ptr;}
vector< pair<int,int> > v[MAXN * 65],vv[MAXN * 65];
struct query
{
char ch[65];
int typ,a,b,c;
}q[MAXN];
void insert(int k,int tim,int typ)
{
int l = strlen(q[k].ch);
int cur = 0;
for(int i = 0;i < l;++i)
{
int nxt = q[k].ch[i] - 'a';
if(t[cur].tr[nxt] == 0)t[cur].tr[nxt] = newnode();
cur = t[cur].tr[nxt];
v[cur].push_back(make_pair(tim,typ));
}
return;
}
int getpos(int k)
{
int l = strlen(q[k].ch);
int cur = 0;
for(int i = 0;i < l;++i)
{
int nxt = q[k].ch[i] - 'a';
if(t[cur].tr[nxt] == 0)return -1;
cur = t[cur].tr[nxt];
}
return cur;
}
int ans = 0;
int query(int k,int val)
{//cout << k << " " << val << endl;
int pos = getpos(k);
if(pos == -1)return -1;
vector< pair<int,int> >::iterator it = lower_bound(vv[pos].begin(),vv[pos].end(),make_pair(val,0));
if(it == vv[pos].end() || it -> second > k)return -1;
return it -> second;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)
{
scanf("%d%s",&q[i].typ,q[i].ch);
if(q[i].typ == 3)scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c);
}
for(int i = 1;i <= n;++i)
{
if(q[i].typ == 1)insert(i,i,1);
if(q[i].typ == 2)insert(i,i,-1);
}
for(int i = 1;i <= ptr;++i)
{
int cnt = 0,curmax = 0;
for(vector< pair<int,int> >::iterator it = v[i].begin();it != v[i].end();++it)
{
cnt += it -> second;
if(!vv[i].size() || curmax < cnt)
{
vv[i].push_back(make_pair(cnt,it -> first));
curmax = cnt;
}
}
}
for(int i = 1;i <= n;++i)
{
if(q[i].typ == 3)
{
ans = query(i,(1ll * q[i].a * abs(ans) + q[i].b) % q[i].c + 1);
printf("%d\n",ans);
}
}
return 0;
}