hdu 5790 Prefix (字典树 + 主席树)
来源:互联网 发布:java 字符串排列组合 编辑:程序博客网 时间:2024/05/21 09:28
Prefix
Time Limit: 2000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 519 Accepted Submission(s): 157
Problem Description
Alice gets N strings. Now she has Q questions to ask you. For each question, she wanna know how many different prefix strings between Lth and Rth strings. It's so easy right? So solve it!
Input
The input contains multiple test cases.
For each test case, the first line contains one integerN(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.
For each test case, the first line contains one integer
Output
For each question, output the answer.
Sample Input
3abcababaa30 20 11 1
Sample Output
763
思路 因为 f (x) 是一个包含z的函数 而 z 是基于每次给出的答案 (初始的z 是 0) 所以强制在线
题目说 所以建一棵字典树 节点保存最后出现的字符串的编号
在建树的时候 把每个字符串走过的节点的数据存进另一个数组arr 并更新这个节点
可以再开个数组 nb 保存一下每个字符串添加进去 字典树的节点数 (1 ~ i 的前缀数)
然后我们可以 得出 ANS = nb[r] - nb[l-1] + ( arr[l 的首字符位置 ] ~~ arr[r 尾字符] 中比 l 小的个数 )
统计 比l 小的个数的 用主席树维护
昨天TLE到- - 于是今天看了下主席树的讲解 也不知道这个 嗯 算不算正常的主席树
#include<iostream>#include<algorithm>#include<cstdlib>#include<cctype>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<set>#include<map>#include<queue>#include<cmath>#include<bitset>#define pi acos(-1.0)#define inf 1<<29#define INF 0x3f3f3f3f#define zero 1e-8const int li[] = { -1, 0, 1, 0};const int lj[] = {0, -1, 0, 1};using namespace std;const int N = 100007 + 107;struct node { int next[27]; int cnt;} tree[N];int fin, least;struct lo { int l, r, data; lo(){l=r=data=0;} void show() { cout << "l: " << l << " r: " << r << " data: " << data << endl; }} cmtree[N * 21];int root[N];int pt;int sum;int nb[N], arr[21*N], lef[N], arrnum;char str[N];int tot, treenum;int cnt;void init(){ arrnum = treenum = 0; memset(tree,0,sizeof(tree)); memset(cmtree,0,sizeof(cmtree)); sum=pt = 0;}void build(int i, int num, int id){ if (str[i] == '\0') return; if (!tree[num].next[str[i] - 'a']) { tree[num].next[str[i] - 'a'] = (++treenum); arr[++arrnum] = id; } else { arr[++arrnum] = tree[tree[num].next[str[i] - 'a']].cnt; } tree[tree[num].next[str[i] - 'a']].cnt = id; build(i + 1, tree[num].next[str[i] - 'a'], id);}void show(){ for (int i = 0; i < 17; ++i) cout << "i: " << i << " arr: " << arr[i] << " lef" << lef[i] << " nb" << nb[i] << endl;}void build(int from, int node, int left, int right, int arrow){ ++pt; int now = pt; if (arrow == 1) cmtree[from].l = pt; else cmtree[from].r = pt; if (left == right) { cmtree[pt].l = cmtree[pt].r = -1; cmtree[pt].data = 0; return; } build(now, node * 2, left, (left + right) / 2, 1); build(now, node * 2 + 1, (left + right) / 2 + 1, right, 2); return;}void update(int node, int left, int right, int from, int mod, int data, int arrow){ ++pt; int now = pt; if (arrow == 1) cmtree[from].l = pt; else cmtree[from].r = pt; int mid = (left + right) / 2; if (left == right) { cmtree[pt].data = cmtree[mod].data + 1; cmtree[pt].l = cmtree[pt].r = -1; return; } if (data <= mid) { update(node * 2, left, mid, pt, cmtree[mod].l, data, 1); cmtree[now].r = cmtree[mod].r; } else { update(node * 2 + 1, mid + 1, right, pt, cmtree[mod].r, data, 2); cmtree[now].l = cmtree[mod].l; } cmtree[now].data = cmtree[cmtree[now].l].data + cmtree[cmtree[now].r].data;}void query(int node, int left, int right, int Begin, int End, int next){ if (left > End || right < Begin) return ; if (left >= Begin && right <= End) { sum += cmtree[next].data; return; } int mid = (left + right) / 2; query(node * 2, left, mid, Begin, End, cmtree[next].l); query(node * 2 + 1, mid + 1, right, Begin, End, cmtree[next].r);}int main(){ int n; while (~scanf("%d", &n)) { init(); for (int i = 1; i <= n; ++i) { scanf("%s", str); lef[i] = arrnum + 1; build(0, 0, i); nb[i] = treenum; } lef[n + 1] = arrnum + 1; pt = 0; root[0] = pt; build(root[0], 1, 1, n, 1); for (int i = 1; i <= arrnum; ++i) { root[i] = ++pt; update(1, 1, n, root[i], root[i - 1] + 1, arr[i], 1); } int m; scanf("%d", &m); int z = 0; for (int i = 0; i < m; ++i) { int l, r; scanf("%d %d", &l, &r); l = (z + l) % n + 1; r = (z + r) % n + 1; if(l > r) swap(l, r); sum = fin = 0; if (l > 1) { query(1, 1, n, 1, l - 1, root[lef[r+1]-1] + 1); int ans1 = sum; sum = 0; query(1, 1, n, 1, l - 1, root[lef[l]-1] + 1); int ans2 = sum; fin = ans1 - ans2; } z = nb[r] - nb[l - 1] + fin; printf("%d\n", z); } } return 0;}
0 0
- hdu 5790 Prefix(字典树+主席树)
- hdu 5790 Prefix (字典树 + 主席树)
- HDU 5790 Prefix(字典树、主席树)
- hdu 5790 prefix 主席树
- [HDU5790] Prefix 字典树+主席树
- [HDU 5790] Prefix (字符串hash+主席树)
- hdu 5790 Prefix(trie+主席树,好题)
- 2016多校第五场 1010 HDU 5790 Prefix 主席树
- hdu 5790 prefix 主席树在线维护区间不同数的个数
- 【主席树】Codechef Prefix XOR
- [主席树] Codechef: Prefix XOR
- DNA Prefix--字典树
- hdu5790 Prefix(Trie树+主席树)
- DNA Prefix (字典树)
- hdu 4866 主席树
- hdu 4348 主席树
- HDU 4417 主席树
- HDU 4417 (主席树)
- opencl获取kerenl运行时间
- android字符串的单复数处理
- Tomcat启动过程分析(上)
- 对称算法(计算机图形学)
- HDU 1213 并查集
- hdu 5790 Prefix (字典树 + 主席树)
- HDU 2196 Computer [树形dp]
- 用一个二维码做下载地址,自动区分是 ios 还是 android
- 【POJ 1389】Area of Simple Polygons(线段树+扫描线)
- Android eclipse sdk包升级
- 使用Spring JdbcTemplate调用存储过程
- android 中转换不同坐标系
- POJ 2142 The Balance
- Semaphore