1 条题解

  • 0
    @ 2025-8-24 22:09:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar nofind
    苟到省选退役的蒟蒻

    搬运于2025-08-24 22:09:41,当前版本为作者最后更新于2019-07-08 08:44:18,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题意:https://www.luogu.org/problemnew/show/P5335

    本篇题解主要是为学长补个代码~

    说下做法:

    我们把学生姓名插入一个trie树,同时对每个节点维护一个sum数组

    插入或删除一个字符串,就在路径上的sum上+1、-1,当sum第一次大于vector的size(即突破了之前的数量),就在vector后插入事件时间time

    查询的时候暴力在trie上查询即可。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1000010;
    int n,ans,tot;
    int sum[maxn];
    int trie[maxn][26];
    char s[maxn];
    vector<int>a[maxn];
    void insert(char *s,int delta,int id)
    {
        int len=strlen(s+1),now=0;
        for(int i=1;i<=len;i++)
        {
            int c=s[i]-'a';
            if(!trie[now][c]) trie[now][c]=++tot;
            now=trie[now][c];
            sum[now]+=delta;
            if(sum[now]>(int)a[now].size()) a[now].push_back(id);
        }
    }
    int query(char *s,int k)
    {
        int len=strlen(s+1),now=0;
        for(int i=1;i<=len;i++)
        {
            int c=s[i]-'a';
            now=trie[now][c];
            if((int)a[now].size()<=k) return -1;//注意超过:<= 
        }
        return a[now][k];
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int op;scanf("%d",&op);
            if(op==1) scanf("%s",s+1),insert(s,1,i);
            if(op==2) scanf("%s",s+1),insert(s,-1,i);
            if(op==3)
            {
                scanf("%s",s+1);
                ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
                ll num=(a*(ll)abs(ans)+b)%c;
                ans=query(s,(int)num);printf("%d\n",ans);
            }
        }
        return 0;
    }
    
    • 1

    信息

    ID
    4331
    时间
    1000ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者