首页 > 代码库 > BZOJ4896 [Thu Summer Camp2016]补退选

BZOJ4896 [Thu Summer Camp2016]补退选

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

 

 

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

 

题目链接:BZOJ4896

正解:$Trie+vector$

解题报告:

  $THUSC2016$ $T2$

  考虑每次加入删除对出现次数的影响只会加减一,那么我可以先用$Trie$来维护整个问题中出现的字符串,然后对于每个节点我都记录一下以当前串为前缀的字符串个数,同时开个$vector$维护出现次数为$x$时的最早时刻。

  因为每次修改只会加减一,那么空间与字符串长度同级,这个用$vector$实现很方便。

 

 

//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int MAXN = 100011;
int n,ch[MAXN*60][10],c[MAXN*60],len,S,cnt,ans;
char s[MAXN];
vector<int>w[MAXN*60];

inline int getint(){
    int w=0,q=0; char c=getchar(); while((c<‘0‘||c>‘9‘) && c!=‘-‘) c=getchar();
    if(c==‘-‘) q=1,c=getchar(); while (c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w;
}

inline void work(){
	n=getint(); S=cnt=1; int type,u,now; LL x,A,B,C;
	for(int o=1;o<=n;o++) {
		type=getint(); u=S;
		scanf("%s",s); len=strlen(s);
		if(type==1) {
			for(int i=0;i<len;i++) {
				now=s[i]-‘a‘; if(!ch[u][now]) ch[u][now]=++cnt;
				u=ch[u][now]; c[u]++;
				if(c[u]>(int)w[u].size()) w[u].push_back(o);
			}
		}
		else if(type==2) {
			for(int i=0;i<len;i++) {
				now=s[i]-‘a‘;
				u=ch[u][now]; c[u]--;
			}
		}
		else {
			u=S; scanf("%lld%lld%lld",&A,&B,&C);
			ans=abs(ans);//!!!
			x=1LL*ans*A%C; x+=B; x%=C;
			ans=0;
			for(int i=0;i<len;i++) {
				now=s[i]-‘a‘;
				if(!ch[u][now]) { ans=-1; break; }
				u=ch[u][now];
			}
			if(ans!=-1) {
				if((int)w[u].size()<=x) ans=-1;
				else ans=w[u][x];
			}
			printf("%d\n",ans);
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("selection.in","r",stdin);
	freopen("selection.out","w",stdout);
#endif
    work();
    return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

  

 

BZOJ4896 [Thu Summer Camp2016]补退选