[BZOJ 3439]Kpm的MC密码
2018-02-05 21:39
295 查看
Description
题库链接给出 \(n\) 个字符串,从 \(1\sim n\) 编号。问对于每个字符串,以其作为后缀的第 \(K_i\) 小的字符串编号为多少。
\(1\leq n\leq 1000000,\sum\limits_{i=1}^n lenth(string(i))\leq 300000\)
Solution
按照套路,把后缀变为前缀,显然是可以在 \(Trie\) 树上解决这个问题。而对于查询第 \(K\) 小,我们可以每个节点开一个权值线段树,遍历字符串时,就将路径上的权值线段树更新。
其他的就是线段树和 \(Trie\) 树的操作了。
Code
//It is made by Awson on 2018.2.5 #include <bits/stdc++.h> #define LL long long #define dob complex<double> #define Abs(a) ((a) < 0 ? (-(a)) : (a)) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) #define writeln(x) (write(x), putchar('\n')) #define lowbit(x) ((x)&(-(x))) using namespace std; const int N = 300000; const int M = 1000000; void read(int &x) { char ch; bool flag = 0; for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); x *= 1-2*flag; } void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); } void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, k, ans[M+5]; char c[N+5]; struct Segment_tree { int root[N+5], ch[N*20+5][2], key[N*20+5], pos; void insert(int &o, int l, int r, int loc) { if (!o) o = ++pos; ++key[o]; if (l == r) return; int mid = (l+r)>>1; if (loc <= mid) insert(ch[o][0], l, mid, loc); else insert(ch[o][1], mid+1, r, loc); } int query(int o, int l, int r, int k) { if (l == r) return l; if (key[o] < k) return -1; int mid = (l+r)>>1; if (key[ch[o][0]] < k) return query(ch[o][1], mid+1, r, k-key[ch[o][0]]); else return query(ch[o][0], l, mid, k); } }T; struct Trie { int ch[N+5][26], pos; void insert(int id) { int len = strlen(c), u = 0; for (int i = len-1; i >= 0; i--) { if (ch[u][c[i]-'a'] == 0) ch[u][c[i]-'a'] = ++pos; u = ch[u][c[i]-'a']; T.insert(T.root[u], 1, n, id); } ans[id] = u; } }Tr; void work() { read(n); for (int i = 1; i <= n; i++) { scanf("%s", c); Tr.insert(i); } for (int i = 1; i <= n; i++) { read(k); writeln(T.query(T.root[ans[i]], 1, n, k)); } } int main() { work(); return 0; }
相关文章推荐
- BZOJ3439 Kpm的MC密码
- bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)
- [BZOJ]3439: Kpm的MC密码 trie树+主席树(线段树合并)
- BZOJ3439: Kpm的MC密码
- BZOJ3439 Kpm的MC密码(可持久化trie)
- bzoj 3439: Kpm的MC密码
- bzoj3439 Kpm的MC密码
- bzoj 3439: Kpm的MC密码
- 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
- bzoj 3439: Kpm的MC密码 Trie+动态开点线段树
- BZOJ-3439 Kpm的MC密码
- 【BZOJ3439】Kpm的MC密码 Trie+dfs序+可持久化线段树
- 【BZOJ3439】 Kpm的MC密码 (TRIE+主席树)
- 【bzoj3439】Kpm的MC密码 trie树+主席树
- bzoj 3439: Kpm的MC密码
- 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 【bzoj3439】kpm的mc密码 题解
- BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
- BZOJ3439: Kpm的MC密码