BZOJ4896 THUSC2016补退选(trie)
字符串扔进trie,vector记录每个前缀出现次数的最大值的更新记录即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define ll long long #define N 100010 #define M 66 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int m,lastans,t,cnt,root; char s[M]; struct data{int mx,x,ch[10]; }tree[N*M]; vector<int> a[N*M],b[N*M]; void ins(int &k,int p,int n,int x,int i) { if (!k) k=++cnt;tree[k].x+=x; if (tree[k].x>tree[k].mx) a[k].push_back(tree[k].mx=tree[k].x),b[k].push_back(i); if (p==n) return; ins(tree[k].ch[s[p+1]-'a'],p+1,n,x,i); } int find(int k,int p,int n) { if (p==n) return k; return find(tree[k].ch[s[p+1]-'a'],p+1,n); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4896.in","r",stdin); freopen("bzoj4896.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif m=read(); for (int i=1;i<=m;i++) { int op=read();scanf("%s",s+1);int n=strlen(s+1); if (op==3) { int A=read(),B=read(),C=read(); int x=(1ll*A*abs(lastans)+B)%C+1; int k=find(root,0,n); int u=lower_bound(a[k].begin(),a[k].end(),x)-a[k].begin(); if (u>=b[k].size()) lastans=-1; else lastans=b[k][u]; printf("%d\n",lastans); } else ins(root,0,n,op==1?1:-1,i); } return 0; }