[THUSC 2016] 补退选 (Trie树)

link

$solution:$

$Trie$树很显然吧,那么如何去处理每次询问。对于$Trie$树的每个节点放一个$vector$表示其若有$v$个人的最小时间。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=1000001;
vector<int> ve[MAXN];
int ch[MAXN][11],tot,Time[MAXN];
struct Trie{
    void insert(char *s,int opt,int k){
        int len=strlen(s),u=1;
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!ch[u][c]) ch[u][c]=++tot;
            u=ch[u][c];
            Time[u]+=opt;
            if(Time[u]>ve[u].size()) ve[u].push_back(k);
        }
    }
    int Query(char *s){
        int len=strlen(s),u=1;
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!ch[u][c]) return -1;
            u=ch[u][c];
        }return u;
    }
}trie;
int n,ans;
char str[61];
int main(){
    // freopen("2.in","r",stdin);
     n=read();
     for(int i=1;i<=n;i++){
         int opt=read();
         if(opt==1){
             scanf("%s",str);
             trie.insert(str,1,i);
         }
         if(opt==2){
             scanf("%s",str);
             trie.insert(str,-1,i);
         }
         if(opt==3){
             scanf("%s",str);
             int pos=trie.Query(str);
             ll a=read(),b=read(),c=read();
             ans=abs(ans);
             ll k=(a*ans+b)%c;
             k=(int)k;
             /*printf("k:%d\n",k);
             printf("siz:%d\n",ve[pos][0]);*/
             if(pos==-1){ans=-1;printf("%d\n",ans);continue;}
             if(ve[pos].size()>k){printf("%d\n",ans=ve[pos][k]);continue;}
             else {ans=-1;printf("%d\n",ans);continue;}
             
         }
     }
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/10555827.html