CF666E Forensic Examination 题解
1.CF505E Mr. Kitayuta vs. Bamboos 题解2.CF506E Mr. Kitayuta's Gift 题解3.CF512D Fox And Travelling 题解4.CF516D Drazil and Morning Exercise 题解5.CF516E Drazil and His Happy Friends 题解6.CF521D Shop 题解7.CF521E Cycling City 题解8.CF527E Data Center Drama 题解9.CF547D Mike and Fish 题解10.CF559E Gerald and Path 题解11.CF568C New Language 题解12.CF576D Flights for Regular Customers 题解13.CF578E Walking! 题解14.CF585F Digits of Number Pi 题解15.CF605E Intergalaxy Trips 题解16.CF613E Puzzle Lover 题解17.CF626G Raffles 题解18.CF526G Spiders Evil Plan 题解19.CF538G Berserk Robot 题解20.CF538H Summer Dichotomy 题解21.CF553E Kyoya and Train 题解22.CF566C Logistical Questions 题解23.CF566E Restoring Map 题解24.CF568E Longest Increasing Subsequence 题解25.CF571E Geometric Progressions 题解26.CF573E Bear and Bowling 题解27.CF578F Mirror Box 题解28.[AGC038E] Gachapon 题解
29.CF666E Forensic Examination 题解
30.CF671E Organizing a Race 题解Description
给你一个串
如有多解输出最靠前的那一个。
Solution
首先将
考虑将
线段树合并即可。
时间复杂度:
Code
#include <bits/stdc++.h> // #define int int64_t using pii = std::pair<int, int>; const int kMaxN = 5e5 + 5, kMaxL = 6e5 + 5; struct Node { int ls, rs; pii p; } tt[kMaxL * 50]; int n, m, q, len, cnt; int a[kMaxL], sa[kMaxL], rk[kMaxL], height[kMaxL], bel[kMaxL]; int fa[kMaxL], idd[kMaxL], val[kMaxL * 2], p[kMaxL * 2][22]; int rt[kMaxL * 2]; pii ans[kMaxN]; std::string s, t[kMaxN]; std::vector<int> T[kMaxL * 2]; std::vector<std::tuple<int, int, int>> qq[kMaxL * 2]; pii merge(pii a, pii b) { if (!a.first) a.second = -1e9; if (!b.first) b.second = -1e9; if (a.second > b.second) return a; else if (a.second < b.second) return b; else return std::min(a, b); } void getsa(int n, int *a, int *sa, int *rk) { static int cnt[kMaxL], id[kMaxL], ork[kMaxL * 2] = {0}; for (int i = 1; i <= n; ++i) ++a[i]; int v = *std::max_element(a + 1, a + 1 + n), m = 0; for (int i = 1; i <= n; ++i) ++cnt[a[i]]; for (int i = 1; i <= v; ++i) cnt[i] += cnt[i - 1]; for (int i = n; i; --i) sa[cnt[a[i]]--] = i; for (int i = 1; i <= n; ++i) { if (a[sa[i]] == a[sa[i - 1]]) rk[sa[i]] = rk[sa[i - 1]]; else rk[sa[i]] = ++m; } for (int w = 1; m < n; w <<= 1) { for (int i = 1; i <= n; ++i) ork[i] = rk[i]; int p = 0; for (int i = n - w + 1; i <= n; ++i) id[++p] = i; for (int i = 1; i <= n; ++i) if (sa[i] > w) id[++p] = sa[i] - w; std::fill_n(cnt + 1, m, 0); for (int i = 1; i <= n; ++i) ++cnt[rk[i]]; for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1]; for (int i = n; i; --i) sa[cnt[rk[id[i]]]--] = id[i]; m = 0; for (int i = 1; i <= n; ++i) { if (ork[sa[i]] == ork[sa[i - 1]] && ork[sa[i] + w] == ork[sa[i - 1] + w]) rk[sa[i]] = rk[sa[i - 1]]; else rk[sa[i]] = ++m; } } } void getheight(int n, int *a, int *sa, int *rk, int *height) { for (int i = 1, p = 0; i <= n; ++i) { if (p) --p; int j = sa[rk[i] - 1]; if (i && j && p) assert(a[i + p - 1] == a[j + p - 1]); for (; p < n - std::max(i, j) && a[i + p] == a[j + p]; ++p) {} height[rk[i]] = p; } } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void unionn(int x, int y, int v) { int fx = find(x), fy = find(y); if (fx != fy) { fa[fx] = fy, val[++cnt] = v; T[cnt].emplace_back(idd[fx]), T[cnt].emplace_back(idd[fy]); p[idd[fx]][0] = p[idd[fy]][0] = cnt, idd[fy] = cnt; } } void build() { for (int i = 1; i <= len; ++i) fa[i] = idd[i] = i; cnt = len; std::vector<std::pair<int, int>> vec; for (int i = 2; i <= len; ++i) vec.emplace_back(height[i], i); std::sort(vec.begin(), vec.end(), std::greater<>()); for (auto [v, x] : vec) unionn(x - 1, x, v); } void prework() { int now = 26; for (int i = 1; i <= n; ++i) a[++len] = s[i] - 'a'; a[++len] = ++now; for (int i = 1; i <= m; ++i) { for (int j = 1; j < t[i].size(); ++j) a[++len] = t[i][j] - 'a', bel[len] = i; a[++len] = ++now; } getsa(len, a, sa, rk), getheight(len, a, sa, rk, height), build(); for (int i = cnt; i; --i) for (int j = 1; j <= std::__lg(cnt); ++j) p[i][j] = p[p[i][j - 1]][j - 1]; } std::pair<int, int> solve(int l, int r, int pl, int pr) { static int cnt[kMaxN]; std::fill_n(cnt + 1, m, 0); int mi = 1e9; for (int i = rk[pl] + 1; i <= len; ++i) { mi = std::min(mi, height[i]); if (mi >= pr - pl + 1) ++cnt[bel[sa[i]]]; else break; } mi = 1e9; for (int i = rk[pl]; i > 1; --i) { mi = std::min(mi, height[i]); if (mi >= pr - pl + 1) ++cnt[bel[sa[i - 1]]]; else break; } std::pair<int, int> ret = {-1, -1}; for (int i = l; i <= r; ++i) { if (cnt[i] > ret.second || cnt[i] == ret.second && i < ret.first) ret = {i, cnt[i]}; } return ret; } int gettop(int x, int v) { for (int i = std::__lg(len); ~i; --i) if (val[p[x][i]] >= v) x = p[x][i]; return x; } void pushup(int x) { tt[x].p = merge(tt[tt[x].ls].p, tt[tt[x].rs].p); } void update(int &x, int l, int r, int ql, int v) { static int sgt_cnt = 0; if (!x) x = ++sgt_cnt; if (l == r) { tt[x].p.first = l, tt[x].p.second += v; return; } int mid = (l + r) >> 1; if (ql <= mid) update(tt[x].ls, l, mid, ql, v); else update(tt[x].rs, mid + 1, r, ql, v); pushup(x); } int merge(int x, int y, int l, int r) { if (!x || !y) return x + y; if (l == r) { tt[x].p.first = l, tt[x].p.second += tt[y].p.second; return x; } int mid = (l + r) >> 1; tt[x].ls = merge(tt[x].ls, tt[y].ls, l, mid), tt[x].rs = merge(tt[x].rs, tt[y].rs, mid + 1, r); pushup(x); return x; } pii query(int x, int l, int r, int ql, int qr) { if (l > qr || r < ql) return {0, 0}; else if (!x) return {std::max(l, ql), 0}; else if (l >= ql && r <= qr) return tt[x].p; int mid = (l + r) >> 1; return merge(query(tt[x].ls, l, mid, ql, qr), query(tt[x].rs, mid + 1, r, ql, qr)); } void dfs(int u) { // static int cnt[500][500] = {0}; if (u <= len && bel[sa[u]]) update(rt[u], 1, m, bel[sa[u]], 1); for (auto v : T[u]) { dfs(v); rt[u] = merge(rt[u], rt[v], 1, m); } for (auto [l, r, id] : qq[u]) { // ans[id] = {-1, -1}; // for (int i = l; i <= r; ++i) ans[id] = merge(ans[id], {i, cnt[u][i]}); ans[id] = query(rt[u], 1, m, l, r); } } void dickdreamer() { std::cin >> s >> m; n = s.size(), s = " " + s; for (int i = 1; i <= m; ++i) { std::cin >> t[i]; t[i] = " " + t[i]; } prework(); std::cin >> q; for (int i = 1; i <= q; ++i) { int l, r, pl, pr; std::cin >> l >> r >> pl >> pr; // auto p = solve(l, r, pl, pr); // std::cout << p.first << ' ' << p.second << '\n'; qq[gettop(rk[pl], pr - pl + 1)].emplace_back(l, r, i); } dfs(cnt); for (int i = 1; i <= q; ++i) std::cout << ans[i].first << ' ' << ans[i].second << '\n'; } int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; // std::cin >> T; while (T--) dickdreamer(); // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2024-02-20 P5163 WD与地图 题解