BZOJ3439 Kpm的MC密码
2014-12-01 16:42
232 查看
云神出的题= =,逼得蒟蒻要跳楼了
这道题的话。。。先把读入的字符串反转,然后建trie树
发现一个字符串的kpm串就是他的结尾字符的子树,于是对所有是字符串结尾的点按照dfs序展成一个序列。
问题转化为求区间第k大,用主席树什么的就好了。。。
View Code
这道题的话。。。先把读入的字符串反转,然后建trie树
发现一个字符串的kpm串就是他的结尾字符的子树,于是对所有是字符串结尾的点按照dfs序展成一个序列。
问题转化为求区间第k大,用主席树什么的就好了。。。
/************************************************************** Problem: 3439 User: rausen Language: C++ Result: Accepted Time:1500 ms Memory:62744 kb ****************************************************************/ #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; typedef vector <int> Vec; const int N = 100005; const int Len = 300005; const int M = 2000005; struct trie_node { int son[26], st, ed; Vec tail; } t[Len]; struct seg_node { int lson, rson, num; } tr[M]; int n, cnt_trie = 1, cnt_seq, cnt_seg; int Tail , root ; char st[Len]; int len; inline void read() { char ch = getchar(); while (ch < 'a' || 'z' < ch) ch = getchar(); len = 0; while ('a' <= ch && ch <= 'z') st[++len] = ch, ch = getchar(); } #define ch(j) (int) st[j] - 'a' void build_trie() { int i, j, now; for (i = 1; i <= n; ++i) { read(); reverse(st + 1, st + len + 1); now = 1; for (j = 1; j <= len; ++j) { if (!t[now].son[ch(j)]) t[now].son[ch(j)] = ++cnt_trie; now = t[now].son[ch(j)]; } Tail[i] = now, t[now].tail.push_back(i); } } #define mid (l + r >> 1) void insert(int &p, int l, int r, int pos) { tr[++cnt_seg] = tr[p], p = cnt_seg, ++tr[p].num; if (l == r) return; if (pos <= mid) insert(tr[p].lson, l, mid, pos); else insert(tr[p].rson, mid + 1, r, pos); } int query(int i, int j, int rank) { i = root[i - 1], j = root[j]; if (tr[j].num - tr[i].num < rank) return -1; int l = 1, r = n; while (l != r) { if (tr[tr[j].lson].num - tr[tr[i].lson].num >= rank) r = mid, i = tr[i].lson, j = tr[j].lson; else { rank -= tr[tr[j].lson].num - tr[tr[i].lson].num; l = mid + 1, i = tr[i].rson, j = tr[j].rson; } } return l; } void dfs(int p) { int i, sz = t[p].tail.size(); if (sz) { t[p].st = ++cnt_seq, root[cnt_seq] = root[cnt_seq - 1]; for (i = 0; i < sz; ++i) insert(root[cnt_seq], 1, n, t[p].tail[i]); } for (i = 0; i < 26; ++i) if (t[p].son[i]) dfs(t[p].son[i]); if (sz) t[p].ed = cnt_seq; } int main() { int i, x; scanf("%d\n", &n); build_trie(); dfs(1); for (i = 1; i <= n; ++i) { scanf("%d", &x); printf("%d\n", query(t[Tail[i]].st, t[Tail[i]].ed, x)); } }
View Code
相关文章推荐
- BZOJ-3439 Kpm的MC密码
- 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
- 【BZOJ3439】Kpm的MC密码 Trie+dfs序+可持久化线段树
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
- bzoj 3439: Kpm的MC密码
- [BZOJ3439]Kpm的MC密码
- BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 【BZOJ】【3439】Kpm的MC密码
- [BZOJ 3439]Kpm的MC密码
- BZOJ 3439 Kpm的MC密码 Trie+可持久化线段树
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
- [BZOJ 3439]Kpm的MC密码
- BZOJ 3439 Kpm的MC密码 Trie树+可持久化线段树
- 【bzoj3439】KPM的MC密码
- [BZOJ]3439: Kpm的MC密码 trie树+主席树(线段树合并)
- BZOJ3439 KPM的MC密码
- 【BZOJ3439】 Kpm的MC密码 (TRIE+主席树)
- 【bzoj3439】Kpm的MC密码 可持久化Trie树