bzoj 4896: [Thu Summer Camp2016]补退选 字典树+vector
来源:互联网 发布:豫剧板胡网络培训班 编辑:程序博客网 时间:2024/06/16 10:01
题意
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 个小写字母,强制在线
分析
一开始想到一个O(n*60*logn)的做法,是用可持久化数据结构来实现的,比较麻烦,不过貌似也能过。
其实这题可以只维护一棵字典树,每个节点记录当前以该节点为前缀时的字符串数量,开个vector记录每个长度出现的最小时间。注意只有当前数量大于vector的末尾时才将其加入,然后查找的时候二分一下就好了。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<vector>using namespace std;typedef long long LL;const int N=100005;int n,cnt;struct data{int cnt,num;};struct tree{int to[10],mx,cnt;}t[N*60];vector<data> w[N*60];char s[65];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void ins(int now,int x,int y,int num,int z){ t[now].cnt+=z; if (t[now].cnt>t[now].mx) t[now].mx=t[now].cnt,w[now].push_back((data){t[now].cnt,num}); if (x==y) return; if (!t[now].to[s[x]-'a']) ins(t[now].to[s[x]-'a']=++cnt,x+1,y,num,z); else ins(t[now].to[s[x]-'a'],x+1,y,num,z);}bool cmp(data a,data b){ return a.cnt<b.cnt;}int query(int now,int x,int y,int z){ if (!now) return -1; if (x==y) { vector<data>::iterator it=upper_bound(w[now].begin(),w[now].end(),(data){z,0},cmp); if (it==w[now].end()) return -1; else return (*it).num; } return query(t[now].to[s[x]-'a'],x+1,y,z);}int main(){ n=read();int lastans=0; cnt=1; for (int i=1;i<=n;i++) { int op=read(); scanf("%s",s);int len=strlen(s); if (op==1) ins(1,0,len,i,1); else if (op==2) ins(1,0,len,i,-1); else { int a=read(),b=read(),c=read(),v=((LL)a*abs(lastans)+(LL)b)%c; printf("%d\n",lastans=query(1,0,len,v)); } } return 0;}
阅读全文
0 0
- bzoj 4896: [Thu Summer Camp2016]补退选 字典树+vector
- BZOJ 4896 Thu Summer Camp2016 补退选 Trie树
- 4896: [Thu Summer Camp2016]补退选
- [Trie]BZOJ 4896——[Thu Summer Camp2016]补退选
- 【Trie+vector】BZOJ4896(Thu Summer Camp2016)[补退选]题解
- BZOJ4896 [Thu Summer Camp2016]补退选
- [DP] BZOJ 4897 [Thu Summer Camp2016]成绩单
- [Trie] BZOJ4896: [Thu Summer Camp2016]补退选
- BZOJ4897 [Thu Summer Camp2016]成绩单
- 4897: [Thu Summer Camp2016]成绩单
- BZOJ4897: [Thu Summer Camp2016]成绩单 DP
- 【BZOJ 4103】[Thu Summer Camp 2015]异或运算 可持久化trie树
- BZOJ 4104 [Thu Summer Camp 2015]解密运算
- bzoj 4104: [Thu Summer Camp 2015]解密运算
- bzoj 4103: [Thu Summer Camp 2015]异或运算
- BZOJ 4103: [Thu Summer Camp 2015]异或运算
- BZOJ 4105: [Thu Summer Camp 2015]平方运算
- bzoj 4104: [Thu Summer Camp 2015]解密运算 乱搞
- vue muit-ui infinite-scroll源码解析
- PHP单例模式
- 使用boost::shared_mutex实现读写锁
- 洛谷 P1130 红牌
- SmartRecom:一款干货满满,助你进阶的App项目
- bzoj 4896: [Thu Summer Camp2016]补退选 字典树+vector
- centos7.3配置简单配置 kickstart,实现无人值守安装
- 2017计蒜之道初赛_百度的科学计算器(简单难度)
- 《我是应届生》——2017华为“创想杯”校园开发者大赛纪实
- ESP-12
- java内部类相关的底层实现
- [spring-mvc] DispatcherServlet 参数 namespace contextConfigLocatoin区别
- Java基于无向有权图实现克鲁斯卡尔算法
- 宝塔控制面板忘记密码怎么找回?