THUSC2016

补退选

Luogu
LOJ
比较裸。
建一棵Trie树,记录一下每个节点的\(sum\)表示经过该点的字符串个数,每次暴力插入、删除。
同时每个节点维护一个vector,记录一下这个点的\(sum\)第一次达到(超过)某个值的时间。
容易证明vector的总的元素个数是\(O(\sum|S|)\)的。总的复杂度为\(O(\sum|S|)\)

#include<bits/stdc++.h>
using namespace std;
const int N=100007,M=60*N;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int T=1,cnt,ans,sum[M],ch[M][10];vector<int>t[M];char s[61];
void update(int p)
{
    if(sum[p]<=(int)t[p].size()) return ;
    t[p].push_back(T);
}
void insert()
{
    scanf("%s",s);int len=strlen(s),p=0;++sum[p],update(p);
    for(int i=0,c;i<len;++i)
    {
    if(!ch[p][c=s[i]-'a']) ch[p][c]=++cnt;
    ++sum[p=ch[p][c]],update(p);
    }
}
void remove()
{
    scanf("%s",s);int len=strlen(s),p=0;--sum[p];
    for(int i=0,c;i<len;++i) --sum[p=ch[p][c=s[i]-'a']];
}
void query()
{
    scanf("%s",s);
    int a=read(),b=read(),c=read(),len=strlen(s),p=0;
    a=(1ll*a*abs(ans)+b)%c;
    for(int i=0;i<len;++i) if(!(p=ch[p][s[i]-'a'])) return (void)(printf("%d\n",ans=-1));
    if((int)t[p].size()<=a) return (void)(printf("%d\n",ans=-1));
    printf("%d\n",ans=t[p][a]);
}
int main()
{
    for(int m=read();T<=m;++T)
    switch(read())
    {
    case 1:insert();break;
    case 2:remove();break;
    case 3:query();break;
    }
}

成绩单

Luogu
LOJ

星露谷物语

LOJ

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12004770.html