[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;}
阅读全文
0 0
- [Trie] BZOJ4896: [Thu Summer Camp2016]补退选
- BZOJ4896 [Thu Summer Camp2016]补退选
- 【Trie+vector】BZOJ4896(Thu Summer Camp2016)[补退选]题解
- BZOJ 4896 Thu Summer Camp2016 补退选 Trie树
- [Trie]BZOJ 4896——[Thu Summer Camp2016]补退选
- 4896: [Thu Summer Camp2016]补退选
- BZOJ4897 [Thu Summer Camp2016]成绩单
- 4897: [Thu Summer Camp2016]成绩单
- bzoj 4896: [Thu Summer Camp2016]补退选 字典树+vector
- [DP] BZOJ 4897 [Thu Summer Camp2016]成绩单
- BZOJ4897: [Thu Summer Camp2016]成绩单 DP
- BZOJ 4103 [Thu Summer Camp 2015]异或运算 可持久化Trie
- 【bzoj4103】 【Thu Summer Camp 2015】【异或运算】【可持久化trie】
- 【BZOJ 4103】[Thu Summer Camp 2015]异或运算 可持久化trie树
- bzoj 4103: [Thu Summer Camp 2015]异或运算 可持久化trie
- BZOJ4104 [Thu Summer Camp 2015]解密运算
- [BZOJ4105][Thu Summer Camp 2015]平方运算
- 4104: [Thu Summer Camp 2015]解密运算
- Spring boot快速开发
- HDU 1176
- 动态规划之最长公共子序列
- arttemplate模板--字符串拼接中使用模板语法
- EL表达式三元运算符
- [Trie] BZOJ4896: [Thu Summer Camp2016]补退选
- hdu 1429 胜利大逃亡(续)
- LoadRunner学习笔记——Day2
- Angularjs 双重循环获取父级下标$index
- 使用GDI +加载JPG和PNG资源的CGdiPlusBitmap类
- MongoDB聚合查询
- springboot开发(yml配置和注解解析)
- zend Studio快捷键操作说明
- Java的异常处理