HDU 5790 Prefix(字典树+主席树)
Prefix
Time Limit: 2000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 858 Accepted Submission(s): 256
For each test case, the first line contains one integer N(1≤N≤100000). Then next N lines contain N strings and the total length of N strings is between 1 and 100000. The next line contains one integer Q(1≤Q≤100000). We define a specail integer Z=0. For each query, you get two integer L, R(0=<L,R<N). Then the query interval [L,R] is [min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]. And Z change to the answer of this query.
题目链接:HDU 5790
就是问你[L,R]中的字符串的前缀一共有多少种,那么我们可以把每一个字符串的前缀标号,然后记录这种字符串有几种前缀并更新到主席树上,每一次问[L,R]就变成询问[presum_kind[L-1]+1, presum_kind[R]]之间有几个不同的前缀标号,比如题目样例给前缀标号,就是[1,2,3][1,2,4][5,6,7]。
代码:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(ql) (ql<<1)
#define RC(ql) ((ql<<1)+1)
#define MID(ql,qr) ((ql+qr)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100010;
struct Trie
{
int nxt[26];
int id;
void reset()
{
fill(nxt, nxt + 26, 0);
id = 0;
}
};
struct seg
{
int lson, rson;
int cnt;
void reset()
{
lson = rson = 0;
cnt = 0;
}
};
Trie L[N];
seg T[N * 36];
int sz, tot, tid, arr[N], Tot;
int lenth[N], last[N], root[N];
char s[N]; void init()
{
sz = 1;
tot = 0;
tid = 0;
Tot = 0;
CLR(last, 0);
L[0].reset();
}
void update(int &cur, int ori, int l, int r, int pos, int flag)
{
cur = ++tot;
T[cur] = T[ori];
T[cur].cnt += flag;
if (l == r)
return ;
int mid = MID(l, r);
if (pos <= mid)
update(T[cur].lson, T[ori].lson, l, mid, pos, flag);
else
update(T[cur].rson, T[ori].rson, mid + 1, r, pos, flag);
}
int query(int S, int E, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return T[E].cnt - T[S].cnt;
else
{
int ret = 0;
int mid = MID(l, r);
if (ql <= mid)
ret += query(T[S].lson, T[E].lson, l, mid, ql, qr);
if (qr > mid)
ret += query(T[S].rson, T[E].rson, mid + 1, r, ql, qr);
return ret;
}
}
int insert(int id, char s[])
{
int len = strlen(s);
int u = 0;
for (int i = 0; i < len; ++i)
{
int v = s[i] - 'a';
if (!L[u].nxt[v])
{
L[sz].reset();
L[u].nxt[v] = sz++;
}
u = L[u].nxt[v];
if (L[u].id == 0)
L[u].id = ++tid;
arr[++Tot] = L[u].id;
}
lenth[id] = Tot;
return len;
}
int main(void)
{
int n, m, i, l, r;
while (~scanf("%d%d", &n, &m))
{
init();
for (i = 0; i < n; ++i)
{
scanf("%s", s);
insert(i, s);
}
for (i = 1; i <= Tot; ++i)
{
if (!last[arr[i]])
update(root[i], root[i - 1], 1, Tot, i, 1);
else
{
int tmp;
update(tmp, root[i - 1], 1, Tot, last[arr[i]], -1);
update(root[i], tmp, 1, Tot, i, 1);
}
last[arr[i]] = i;
}
scanf("%d", &m);
int ans = 0;
while (m--)
{
int L, R;
scanf("%d%d", &L, &R);
l = min((L + ans) % n, (R + ans) % n);
r = max((L + ans) % n, (R + ans) % n);
L = l - 1 >= 0 ? lenth[l - 1] : 0;
R = lenth[r];
printf("%d\n", ans = query(root[L], root[R], 1, Tot, L + 1, R));
}
}
return 0;
}
HDU 5790 Prefix(字典树+主席树)的更多相关文章
- HDU 5790 Prefix(Hash + 主席树)
题目链接 Prefix 题意 给定一个字符串序列,求第$l$个字符串到第$r$个字符串之间有多少个不同的前缀 强制在线 考虑$Hash$ 首先把所有前缀都$hash$出来,按顺序组成一个长度不超过 ...
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- HDU5790 Prefix 字典树+主席树
分析:这个题和spoj的d_query是一个题,那个是求一段区间里有多少个不同的数字,这里是统计有多少个不同的前缀 用字典树进行判重,(和查询不同的数字一样)对于每个不同的前缀,只保留它最后一次出现的 ...
- HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- hdu 4417 Super Mario (主席树)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意: 给你段长为n的序列,有q个询问,每次询问区间[l.r]内有多少个数小于等于k 思路: 之前用 ...
- hdu 4348 To the moon (主席树)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4348 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q ...
- HDU 4348 To the moon 主席树 在线更新
http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...
- hdu5790 Prefix(Trie树+主席树)
Problem Description Alice gets N strings. Now she has Q questions to ask you. For each question, she ...
随机推荐
- Redux初识
1.定义规则counter 2.根据计算规则生成store let store=createStore(counter); 3.订阅消息(state 发生变化后发送消息) 4.触发规则,使state发 ...
- javascript遍历方法总结
forEach 循环 JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的: for (var index = 0; index < myArray.lengt ...
- 判断移动端和pc端最简单的方法
<!DOCTYPE html><html><head> <title></title> <script type="text ...
- rootfls(根操作系统)
rootfs根文件系统,linux下的任何目录都是rootfs的一个路径 Files 文件 Directory 目录 FHS(文件层级标准)规定了linux发行标准,也就是一些固定的文件存储 文件 ...
- 笔记--tslib 编译
tslib 是qt启动时的一个触屏校正检验程序. 它的配置以及编译比较简单. 第一步, 下载tslib源码包: http://download.csdn.net/detail/MKNDG/329156 ...
- 30-RoutingMiddleware介绍以及MVC引入
1-构建路由 public class Startup { // This method gets called by the runtime. Use this method to add serv ...
- Windows GitLab使用全过程
1.首先安装Git 1.1.下载网站: https://git-for-windows.github.io/ 1.2.安装Git参考网站 http://blog.csdn.net/u012614287 ...
- Android Studio的Log日志调试
本人菜鸟一枚,极大发挥了搜索的功能.现记录一番,以备后患. 用断点真的很烦,因为之前写linux的时候,就是用最蠢但是也是挺有帮助的printf()来进行调试. 其实用Log输出日志的原理也是差不多的 ...
- C#冒泡算法复习
C#冒泡算法复习 冒泡算法的意思:每一趟找到一个最小或最大的数放到最后面,比较总数的n-1次(因为比较是2个双双比较的) 第一层循环表示进行比较的次数,总共要比较(数的)-1次 (因为比较是2个双双比 ...
- 《移动App性能评测与优化》读书笔记
第一章:内存 内存的主要组成索引: Native Heap:Native代码分配的内存,虚拟机和Android框架本身也会分配 Dalvik Heap:Java代码分配的对象 Dalvik Oth ...