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;
}
 posted on 2020-08-26 16:30  15101051  阅读(61)  评论(0编辑  收藏  举报