题目描述

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

输入

第一行包含一个正整数n,表示一共发生了n个事件。
接下来n行,每行描述一个事件;每行第一个正整数k表示事件类型:
1.如果k=1,表示选课事件,接下来一个字符串S,表示一个姓名为S的学生选了X老师的课
2.如果k=2,表示退课事件,接下来一个字符串S,表示一个姓名为S的学生退了X老师的课
3.如果k=3,表示查询事件,接下来一个字符串S以及三个非负整数a,b,c,表示X老师想知道最早在第几个事件之后,姓名以S为前缀的学生数量超过了(a*|ANS|+b)%c,|ANS|表示上次查询事件的答案的绝对值,如果当前是第一次查询,则|ANS|=0;如果任何时刻都没有超过该值,则答案为-1。注:输入中的所有字符串均只包含小写字母。

输出

对于每个查询事件,输出一行表示该查询答案。

样例输入

6
1 lcaq
3 lca 0 0 5
1 lcq
3 lc 0 1 5
2 lcaq
3 lc 0 1 5

样例输出

1
3
3


题解

Trie树+STL-vector(不需要可持久化)

由于对答案有贡献,只有当某个前缀的字符串数量第一次超过某值。

所以我们可以建立一棵Trie树,根到每个节点的路径表示一个前缀。

在每个节点上开一个vector,记录该前缀的字符串数量第一次超过0、1、...时的事件编号。

这样在查询的时候可以直接找到该前缀的vector,判断并输出即可。

另外,尽管样例中出现了l、q等非前10个字母,但开前10个字母的的数组,亲测是可以过的。

所以经计算,极限空间复杂度为O(n*60*(10+1+1)),并不会炸空间。

(当然开26个字母,把Trie树节点强行压到300000也是可以过的(所以不存在正解,因为无论如何都会MLE))。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define N 6000010
using namespace std;
vector<int> v[N];
int next[N][10] , now[N] , tot;
char str[100];
int main()
{
int n , i , j , t , l , last = 0 , opt , a , b , c;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d%s" , &opt , str) , l = strlen(str);
if(opt == 1)
{
for(t = j = 0 ; j < l ; j ++ )
{
if(!next[t][str[j] - 'a']) next[t][str[j] - 'a'] = ++tot;
t = next[t][str[j] - 'a'] , now[t] ++ ;
if(v[t].size() < now[t]) v[t].push_back(i);
}
}
else if(opt == 2)
for(t = j = 0 ; j < l ; j ++ )
t = next[t][str[j] - 'a'] , now[t] -- ;
else
{
scanf("%d%d%d" , &a , &b , &c) , a = ((long long)a * abs(last) + b) % c;
for(t = j = 0 ; j < l ; j ++ )
{
if(!next[t][str[j] - 'a']) next[t][str[j] - 'a'] = ++tot;
t = next[t][str[j] - 'a'];
}
if(v[t].size() <= a) last = -1;
else last = v[t][a];
printf("%d\n" , last);
}
}
return 0;
}

【bzoj4896】[Thu Summer Camp2016]补退选 Trie树+STL-vector的更多相关文章

  1. 【BZOJ4896】[Thu Summer Camp2016]补退选 Trie树

    [BZOJ4896][Thu Summer Camp2016]补退选 Description X是T大的一名老师,每年他都要教授许多学生基础的C++知识.在T大,每个学生在每学期的开学前都需要选课,每 ...

  2. BZOJ 4896 :[Thu Summer Camp2016]补退选 Trie树+Vector

    4896: [Thu Summer Camp2016]补退选 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 315  Solved: 97[Submi ...

  3. BZOJ4896 [Thu Summer Camp2016]补退选 【trie树】

    题目链接 BZOJ4896 题解 \(thu\)怎么那么喜欢出\(trie\)树的题... 我们当然可以按题意模拟建\(trie\) 询问的时候,由于存在删除操作,不满足单调性,不能直接二分答案 我们 ...

  4. BZOJ 4896 [Thusc2016]补退选 (Trie树维护vector)

    题目大意:略 这竟然是$thusc$的题... 先把询问里加入的串全拎出来,建出$Trie$树,$Trie$里每个节点都开一个$vector$记录操作标号,再记录操作数量$sum$ 然后瞎**搞搞就行 ...

  5. BZOJ4896 [Thu Summer Camp2016]补退选

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. BZOJ 4896: [Thu Summer Camp2016]补退选

    trie树+vector+二分 别忘了abs(ans) #include<cstdio> #include<algorithm> #include<vector> ...

  7. [Thu Summer Camp2016]补退选

    题目描述不说了. 题解: Trie+vector…… Trie存学生,vector存答案. 极为无脑但无脑到让人怀疑 代码: #include<cmath> #include<vec ...

  8. [BZOJ4896][THUSC2016]补退选(Trie)

    4896: [Thu Summer Camp2016]补退选 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 653  Solved: 228[Subm ...

  9. LOJ 2991 「THUSC 2016」补退选——trie+线段树合并或vector

    题目:https://loj.ac/problem/2291 想了线段树合并的做法.就是用线段树维护 trie 的每个点在各种时间的操作. 然后线段树合并一番,线段树维护前缀最大值,就是维护最大子段和 ...

随机推荐

  1. Aizu 2301 Sleeping Time(概率,剪枝)

    根据概率公式dfs即可,判断和区间[T-E,T+E]是否有交,控制层数. #include<bits/stdc++.h> using namespace std; int K,R,L; d ...

  2. 2018.5.30 Oracle数据库PLSQL编程---游标的使用

    显示游标的步骤 /* 显示游标处理步骤 1.声明游标 语法结构:cursor 游标名称 is SQL 语句; 2.打开游标 语法结构:open游标名称; 3.提取数据 语法结构:fetch 4.关闭游 ...

  3. python_13_break

    for i in range(5): print('-----------',i) for j in range(5): print(j) if j>2: break####结束当前循环

  4. javascript oo实现

    很久很久以前,我还是个phper,第一次接触javascript觉得好神奇.跟传统的oo类概念差别很大.记得刚毕业面试,如何在javascript里面实现class一直是很热门的面试题,当前面试百度就 ...

  5. HTML5实现获取地理位置信息并定位功能

    HTML5提供了地理位置定位功能(Geolocation API),能确定用户位置,我们可以借助HTML5的该特性开发基于地理位置信息的应用.本文结合实例给大家分享如何使用HTML5,借助百度.谷歌地 ...

  6. 无线Web开发

    http://am-team.github.io/amg/dev-exp-doc.html

  7. emwin如何在windows10下vs2015或2017进行仿真。

    Make sure the selected Windows SDK is installed:Properties -> Configuration Properties -> Gene ...

  8. 按时按登录IP记录Linux所有用户操作日志的方法(附脚本)

    PS:Linux用户操作记录一般通过命令history来查看历史记录,但是如果因为某人误操作了删除了重要的数据,这种情况下history命令就不会有什么作用了.以下方法可以实现通过记录登陆IP地址和所 ...

  9. kafka 的offset的重置

    最近在spark读取kafka消息时,每次读取都会从kafka最新的offset读取.但是如果数据丢失,如果在使用Kafka来分发消息,在数据处理的过程中可能会出现处理程序出异常或者是其它的错误,会造 ...

  10. MySQL基础9-主键约束、外键约束、等值连接查询、一对一和多对多关系

    1.主键约束和外键约束 外键约束 * 外键必须是另一表的主键的值(外键要引用主键!) * 外键可以重复 * 外键可以为空 * 一张表中可以有多个外键! 概念模型在数据库中成为表 数据库表中的多对一关系 ...