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

 

posted @ 2018-11-28 21:50  Gloid  阅读(178)  评论(0编辑  收藏  举报