【题目链接】
【思路要点】
- 字典树套线段树即可。
- 时空复杂度\(O(NLogN)\)。
【代码】
#includebitsstdc++.h using namespace std; const int MAXN = 1e5 + 5; const int MAXP = 3e6 + 5; template typename T void chkmax(T &x, T y) {x = max(x, y); } template typename T void chkmin(T &x, T y) {x = min(x, y); } template typename T void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x 10 + c - '0'; x = f; } template typename T void write(T x) { if (x 0) x = -x, putchar('-'); if (x 9) write(x 10); putchar(x % 10 + '0'); } template typename T void writeln(T x) { write(x); puts(); } struct info {int val, home; }; char s[MAXN]; info tmp[MAXN]; int n, m, val[MAXN]; struct SegmentTree { struct Node { int lc, rc; int sum; } a[MAXP]; int size, n; void init(int x) { n = x; size = 0; } void update(int root) { a[root].sum = a[a[root].lc].sum + a[a[root].rc].sum; } void modify(int &root, int l, int r, int val) { if (root == 0) root = ++size; if (l == r) { a[root].sum = 1; return; } int mid = (l + r) 2; if (mid = val) modify(a[root].lc, l, mid, val); else modify(a[root].rc, mid + 1, r, val); update(root); } void modify(int &root, int val) { modify(root, 0, n, val); } void query(int root, int l, int r, int cnt) { if (a[root].sum == 0) return; if (l == r) { putchar(' '), write(tmp[l].home); return; } int mid = (l + r) 2; if (a[a[root].lc].sum) query(a[root].lc, l, mid, min(cnt, a[a[root].lc].sum)); cnt -= min(cnt, a[a[root].lc].sum); if (cnt != 0) query(a[root].rc, mid + 1, r, cnt); } void query(int root, int cnt) { int tmp = a[root].sum; write(tmp); chkmin(cnt, tmp); query(root, 0, n, cnt); } } ST; struct Trie { struct Node { int child[26]; int root; vector int stuff; } a[MAXN]; int root, size; void insert(char s, int from) { int now = root, len = strlen(s + 1); for (int i = 1; i = len; i++) { int tmp = s[i] - 'a'; if (a[now].child[tmp] == 0) a[now].child[tmp] = ++size; now = a[now].child[tmp]; a[now].stuff.push_back(from); } } void init() { for (int i = 1; i = size; i++) for (unsigned j = 0; j a[i].stuff.size(); j++) ST.modify(a[i].root, val[a[i].stuff[j]]); } void query(int cnt, char s) { int now = root, len = strlen(s + 1); for (int i = 1; i = len; i++) { int tmp = s[i] - 'a'; now = a[now].child[tmp]; if (now == 0) break; } ST.query(a[now].root, cnt); } } Trie; bool cmp(info a, info b) { return a.val b.val; } int main() { read(n), read(m); for (int i = 0; i = n - 1; i++) { read(val[i]); tmp[i] = (info) {val[i], i}; int k; read(k); while (k--) { scanf( %s, s + 1); Trie.insert(s, i); } } sort(tmp, tmp + n, cmp); for (int i = 0; i = n - 1; i++) val[tmp[i].home] = i; ST.init(n - 1); Trie.init(); while (m--) { int cnt; read(cnt); scanf( %s, s + 1); Trie.query(cnt, s); printf(n); } return 0; }