[Trie] BZOJ4896: [Thu Summer Camp2016]补退选

来源:互联网 发布:php找工作怎么样 编辑:程序博客网 时间:2024/06/09 15:32

题意

X是T大的一名老师,每年他都要教授许多学生基础的C++知识。在T大,每个学生在每学期的开学前都需要选课,每次选课一共分为三个阶段:预选,正选,补退选;其中”补退选”阶段最忙碌。在补退选阶段,学生即可以选课,也可以退课。
对于X老师来说,在补退选阶段可能发生以下两种事件:
1:一个姓名为S的学生选了他的课(姓名S将出现在X的已选课学生名单中)
2:一个姓名为S的学生退了他的课(姓名S将从X的已选课学生名单中移除)
同时,X老师对于有哪些学生选了他的课非常关心,所以他会不定时的查询已选课学生名单,每次查询的格式如下:
最早在哪个事件之后,姓名以S为前缀的学生数量超过了vX老师看你骨骼惊奇,所以想用这个问题考考你,你当然不会畏惧,所以勇敢的接下了这个任务。
注意1:学生的姓名可能相同,如果有p个姓名相同的学生都选了X老师的课,则他们的姓名将出现在X老师的名单上p次。
注意2:只有已经选了课的学生才会退课,如果姓名为S的学生退课,则在他退课之前X老师的名单上一定有姓名S。
注意3:选课,退课和查询都被定义为”事件”,”事件”的编号从1开始。
n<=100000,字符串长度 <= 60,输入中的所有字符串只会包含前 10 个小写字母。
强制在线。

题解

看到前缀容易想到Trie,正常的插入删除,并在每个点上开一个vector记录该前缀出现次数递增变化的时刻序列,询问时在上面二分即可。

#include<cstdio>#include<vector>#include<algorithm>using namespace std;inline char gc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline int getint(){    char ch=gc(); int res=0,ff=1;    while(!('0'<=ch&&ch<='9')){ if(ch=='-') ff=-1; ch=gc(); }    while('0'<=ch&&ch<='9') res=(res<<3)+(res<<1)+ch-'0', ch=gc();    return res*ff;}struct node{    int cnt; vector< pair<int,int> > evt;    node* ch[10];    node(node* son=NULL){ cnt=0; evt.clear(); for(int i=0;i<=9;i++) ch[i]=son; }    } nil, *null=&nil, *root=null;typedef node* P_node;int Q; long long lstans;void Insert(P_node &p,char* now,int k){    if(p==null) p=new node(null);    p->cnt++;     int len=p->evt.size();    if(len==0||p->evt[len-1].first<p->cnt) p->evt.push_back(make_pair(p->cnt,k));    if((*now)=='\000') return; Insert(p->ch[(*now)-'a'],now+1,k);}void Erase(P_node p,char* now){    p->cnt--;     if((*now)=='\000') return;    Erase(p->ch[(*now)-'a'],now+1);}int Query(P_node p,char* now,int val){    if(p==null) return -1;    if((*now)=='\000'){        int len=p->evt.size();        if(len==0||p->evt[len-1].first<val) return -1;        int L=0,R=len-1;        while(L<=R){            int mid=(L+R)>>1;            if(p->evt[mid].first==val) return p->evt[mid].second;            if(p->evt[mid].first<val) L=mid+1;                                 else R=mid-1;        }    }    return Query(p->ch[(*now)-'a'],now+1,val);}char st[65];int main(){    freopen("bzoj4896.in","r",stdin);    freopen("bzoj4896.out","w",stdout);    Q=getint();    for(int ii=1;ii<=Q;ii++){        int pd=getint(),m=-1;        char ch=gc(); while(!('a'<=ch&&ch<='z')) ch=gc();        for(;'a'<=ch&&ch<='z';ch=gc()) st[++m]=ch; st[m+1]='\000';        if(pd==1) Insert(root,st,ii); else        if(pd==2) Erase(root,st); else        if(pd==3){            int t1=getint(),t2=getint(),t3=getint();            if(lstans==-1) lstans=1;            printf("%lld\n",lstans=Query(root,st,(lstans*t1+t2)%t3+1));        }    }    return 0;}
原创粉丝点击