CodeForces Gym 101741 简要题解
2018-03-04 21:08
531 查看
Three Arrays:
枚举 aiai ,求出当前 bb 的合法区间和 cc 的合法区间,并且要求 bb 中的数在 cc 中的合法区间与枚举的 aa 中的数的合法区间有交,然后用前缀和维护一下。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 500005; int d, p, q, r, a , b , c , u , v ; LL ans, L , R ; int Main() { ans = 0; for (int i = 1; i <= p; ++i) { Read(a[i]); } for (int i = 1; i <= q; ++i) { Read(b[i]); } for (int i = 1; i <= r; ++i) { Read(c[i]); } for (int i = 1, c_l = 1, c_r = 0; i <= q; ++i) { for (; c_l <= r && c[c_l] < b[i] - d; ++c_l); for (; c_r < r && c[c_r + 1] <= b[i] + d; ++c_r); u[i] = c_l, v[i] = c_r; L[i] = L[i - 1] + c_l; R[i] = R[i - 1] + c_r; } for (int i = 1, b_l = 1, b_r = 0, c_l = 1, c_r = 0, pos = 0; i <= p; ++i) { for (; c_l <= r && c[c_l] < a[i] - d; ++c_l); for (; c_r < r && c[c_r + 1] <= a[i] + d; ++c_r); for (; b_l <= q && (v[b_l] < c_l || b[b_l] < a[i] - d); ++b_l); for (; b_r < q && b[b_r + 1] <= a[i] + d && u[b_r + 1] <= c_r; ++b_r); for (; pos < q && b[pos + 1] <= a[i]; ++pos); if (b_l <= pos) { ans += R[pos] - R[b_l - 1]; ans -= 1LL * (c_l - 1) * (pos - b_l + 1); } if (pos + 1 <= b_r) { ans += 1LL * (c_r + 1) * (b_r - pos); ans -= L[b_r] - L[pos]; } } printf("%lld\n", ans); return 0; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif while (~scanf("%d %d %d %d", &d, &p, &q, &r)) { Main(); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Expected Shopping:
留坑,不打算填。Cover the Paths:
贪心放即可。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 100005; vector <int> adj ; set <int> s ; int n, m, tot; bool ans ; inline void DFS(int x, int p) { for (auto y : adj[x]) { if (y != p) { DFS(y, x); if (s[x].size() < s[y].size()) { swap(s[x], s[y]); } for (auto i : s[y]) { if (s[x].find(i) != s[x].end()) { ans[x] = true; break; } else { s[x].insert(i); } } } } if (ans[x]) { ++tot, s[x].clear(); } } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n); for (int i = 1, x, y; i < n; ++i) { Read(x), Read(y); adj[x].pb(y), adj[y].pb(x); } Read(m); for (int i = 1, x, y; i <= m; ++i) { Read(x), Read(y); if (x == y) { ans[x] = true; } else { s[x].insert(i), s[y].insert(i); } } DFS(1, 0); printf("%d\n", tot); for (int i = 1; i <= n; ++i) { if (ans[i]) { printf("%d", i); putchar(--tot ? ' ' : '\n'); } } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Elevator:
如果 ti≤tj,ai≤ajti≤tj,ai≤aj 那么 ii 是没用的,可以去掉。fi=min(ti,fj)+2aj+1fi=min(ti,fj)+2aj+1 ,线段树优化即可。
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 200005; int n, top, a , b , sta ; LL f , val[2][N << 2]; inline void Build(int x, int l, int r) { val[0][x] = val[1][x] = 1LL << 60; if (l == r) { return ; } int mid = l + r >> 1; Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r); } inline void Modify(int o, int x, int l, int r, int ql, int qr, LL v) { if (ql > qr) { return ; } if (l == ql && r == qr) { CheckMin(val[o][x], v); return ; } CheckMin(val[o][x << 1], val[o][x]), CheckMin(val[o][x << 1 | 1], val[o][x]); int mid = l + r >> 1; if (qr <= mid) { Modify(o, x << 1, l, mid, ql, qr, v); } else if (ql > mid) { Modify(o, x << 1 | 1, mid + 1, r, ql, qr, v); } else { Modify(o, x << 1, l, mid, ql, mid, v), Modify(o, x << 1 | 1, mid + 1, r, mid + 1, qr, v); } } inline LL Query(int o, int x, int l, int r, int p) { if (l == r) { return val[o][x]; } CheckMin(val[o][x << 1], val[o][x]), CheckMin(val[o][x << 1 | 1], val[o][x]); int mid = l + r >> 1; if (p <= mid) { return Query(o, x << 1, l, mid, p); } else { return Query(o, x << 1 | 1, mid + 1, r, p); } } int Main() { top = 0; for (int i = 1; i <= n; ++i) { Read(a[i]), Read(b[i]); for (; top && b[sta[top]] <= b[i]; --top); sta[++top] = i; } for (int i = 1; i <= top; ++i) { a[i] = a[sta[i]], b[i] = b[sta[i]]; } n = top; Build(1, 1, n); for (int i = 0; i <= n; ++i) { if (i) { f[i] = min(Query(0, 1, 1, n, i), Query(1, 1, 1, n, i) + a[i]); } else { f[i] = 0; } int pos = lower_bound(a + 1, a + n + 1, (int)min(f[i], 1LL << 30)) - a; Modify(0, 1, 1, n, i + 1, pos - 1, f[i] + 2 * b[i + 1]); Modify(1, 1, 1, n, pos, n, 2 * b[i + 1]); } printf("%lld\n", f ); return 0; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif while (~scanf("%d", &n)) { Main(); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Code-Cola Plants:
从 bb 向 aa 连两条边,那么第一组边相当于每个点入度为 11 ,第二组边相当于每个点出度为 11 。构造一个左边 2n2n 个点,右边 mm 个点的二分图,那么就是要求一个最大匹配。
注意到右边每个点度数都是 22 ,所以直接在左边连边,相当于求一个环套树森林。
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 1000005; int n, m, s, t, ql, qr, cnt, d , f , q , ans ; vector <pii> adj ; vector <int> seq; bool v ; inline int Find(int x) { while (x != f[x]) { x = f[x] = f[f[x]]; } return x; } int Main() { for (int i = 1; i <= n << 1; ++i) { f[i] = i, v[i] = false, d[i] = 0, adj[i].clear(); } f[s + n] = t, v[t] = true, cnt = 2, d[t] = d[s + n] = 2; adj[t].pb(mp(s + n, 0)), adj[s + n].pb(mp(t, 0)); adj[t].pb(mp(s + n, 0)), adj[s + n].pb(mp(t, 0)); for (int i = 1, p, q, x, y; i <= m; ++i) { Read(p), Read(q), q += n, x = Find(p), y = Find(q); if (x == y) { if (!v[x]) { adj[p].pb(mp(q, i)), adj[q].pb(mp(p, i)), ++cnt; ++d[p], ++d[q], v[x] = true; } } else if (!v[x] || !v[y]) { adj[p].pb(mp(q, i)), adj[q].pb(mp(p, i)), ++cnt; ++d[p], ++d[q], f[x] = y, v[y] |= v[x]; } ans[i] = -1; } if (cnt != n << 1) { puts("NO"); return 0; } puts("YES"), ql = qr = 0; for (int i = 1; i <= n << 1; ++i) { if (d[i] == 1) { q[++qr] = i; } v[i] = false; } while (ql < qr) { int x = q[++ql]; v[x] = true; for (auto e : adj[x]) { if (!v[e.X]) { ans[e.Y] = x > n; if (--d[e.X] == 1) { q[++qr] = e.X; } } } } for (int i = 1; i <= n << 1; ++i) { if (!v[i]) { seq.clear(); for (int x = i, p; x; ) { v[x] = true, seq.pb(x), p = 0; for (auto e : adj[x]) { if (!v[e.X]) { p = e.X; break; } } x = p; } for (int i = 0, m = seq.size(); i < m; ++i) { for (auto e : adj[seq[i]]) { if (e.X == seq[(i + 1) % m] && !~ans[e.Y]) { ans[e.Y] = seq[i] > n; break; } } } } } for (int i = 1, t = 0; i <= m; ++i) { if (ans[i] == 1) { printf("%d%c", i, ++t == n - 1 ? '\n' : ' '); } } for (int i = 1, t = 0; i <= m; ++i) { if (!ans[i]) { printf("%d%c", i, ++t == n - 1 ? '\n' : ' '); } } return 0; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif while (~scanf("%d %d %d %d", &n, &m, &s, &t)) { Main(); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
GCD:
考虑随机一个保留的数 x=aix=ai ,每次随机有 1212 以上的正确率,多次随机即可。将这个数分解质因数,然后在 gcd(ai,x)gcd(ai,x) 处打上标记,那么每个点实际的标记是它倍数的标记之和。
本质上是一个高维前缀和,单次 σ0(x)×ω(x)σ0(x)×ω(x) 的复杂度可以承受。
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 100005; int n, m, cnt, deg ; LL ans, a , pri ; map <LL, int> val; vector <LL> seq; inline int Rand() { return rand() << 15 | rand(); } inline LL RandLL() { return (LL)Rand() << 30 | Rand(); } inline LL Qul(LL x, LL y, LL mod) { return ((x * y - (LL)(((LD)x * y + 0.5) / mod) * mod) % mod + mod) % mod; } inline LL Qow(LL x, LL y, LL mod) { LL r = 1; for (; y; y >>= 1, x = Qul(x, x, mod)) { if (y & 1) { r = Qul(r, x, mod); } } return r; } inline bool MillerRabin(LL n) { if (n == 2) { return true; } if (n < 2 || !(n & 1)) { return false; } LL a, x, y, u = n - 1; int t = 0; for (; !(u & 1); u >>= 1, ++t); for (int i = 0; i < 10; ++i) { a = RandLL() % (n - 1) + 1, x = Qow(a, u, n); for (int j = 0; j < t; ++j, x = y) { if ((y = Qul(x, x, n)) == 1 && x != 1 && x != n - 1) { return false; } } if (x != 1) { return false; } } return true; } inline LL PollardRho(LL a, LL c) { LL k = 2, x = RandLL() % a, y = x, p = 1; for (LL i = 1; p == 1; ++i) { x = (Qul(x, x, a) + c) % a, p = __gcd(abs(x - y), a); if (i == k) { y = x, k <<= 1; } } return p; } inline void Divide(LL x) { if (x == 1) { return ; } if (MillerRabin(x)) { pri[cnt++] = x; return ; } LL p = x; while (p >= x) { p = PollardRho(x, RandLL() % (x - 1)); } Divide(p), Divide(x / p); } inline void DFS(int x, LL v) { if (x == cnt) { val[v] = 0, seq.pb(v); return ; } for (int i = 0; i <= deg[x]; ++i) { DFS(x + 1, v), v *= pri[x]; } } inline void Solve(LL x) { cnt = 0, Divide(x); sort(pri, pri + cnt); cnt = unique(pri, pri + cnt) - pri; LL tmp = x; for (int i = 0; i < cnt; ++i) { for (deg[i] = 0; tmp % pri[i] == 0; tmp /= pri[i], ++deg[i]); } val.clear(), seq.clear(), DFS(0, 1); for (int i = 0; i < n; ++i) { ++val[__gcd(a[i], x)]; } for (int i = 0; i < cnt; ++i) { for (int j = seq.size() - 1; ~j; --j) { if (seq[j] % pri[i] == 0) { val[seq[j] / pri[i]] += val[seq[j]]; } } } random_shuffle(seq.begin(), seq.end()); for (int i = 0; i < seq.size(); ++i) { if (val[seq[i]] >= n - m) { CheckMax(ans, seq[i]); } } } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif srand(time(0)); Read(n), Read(m); for (int i = 0; i < n; ++i) { Read(a[i]); } while ((double)clock() / CLOCKS_PER_SEC < 3.5) { Solve(a[Rand() % n]); } printf("%lld\n", ans); #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Berland Post:
二分 TT ,跑差分约束。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 2005; const int inf = 0x3f3f3f3f; struct Edge { int p, v; double w; } e[N << 1]; int n, m, e_cnt, a , b , c , d , cnt , hed ; double dis ; bool vis ; char s ; inline void AddEdge(int x, int y, double w) { e[++e_cnt] = {y, hed[x], w}, hed[x] = e_cnt; } inline bool Check(double t) { e_cnt = 0; for (int i = 0; i <= n; ++i) { hed[i] = 0; } for (int i = 1; i <= n; ++i) { if (c[i] != INT_MAX) { AddEdge(0, i, c[i]), AddEdge(i, 0, -c[i]); } } for (int i = 1; i <= m; ++i) { AddEdge(b[i], a[i], t - d[i]); } queue <int> q; for (int i = 0; i <= n; ++i) { dis[i] = 10000000, q.push(i), vis[i] = true, cnt[i] = 0; } dis[0] = 0; while (!q.empty()) { int x = q.front(); q.pop(), vis[x] = false; for (int i = hed[x]; i; i = e[i].v) { if (CheckMin(dis[e[i].p], dis[x] + e[i].w)) { if (++cnt[e[i].p] > n) { return false; } if (!vis[e[i].p]) { vis[e[i].p] = true, q.push(e[i].p); } } } } return true; } int Main() { for (int i = 1; i <= n; ++i) { scanf("%s", s); if (s[0] == '?') { c[i] = INT_MAX; } else { sscanf(s, "%d", &c[i]); } } for (int i = 1; i <= m; ++i) { Read(a[i]), Read(b[i]), Read(d[i]); } double l = 0, r = inf; while (r - l > 1e-5) { double mid = (l + r) / 2; if (Check(mid)) { r = mid; } else { l = mid; } } printf("%lf\n", r), Check(r); for (int i = 1; i <= n; ++i) { printf("%lf%c", dis[i], i == n ? '\n' : ' '); } return 0; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif while (~scanf("%d %d", &n, &m)) { Main(); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Compressed Spanning Subtrees:
考虑每次询问除了 ii 点的剩下 n−1n−1 个点,可以知道 ii 是不是叶子,这里需要询问 ii 次。任选一个叶子 rootroot 当根,对于剩下的每对叶节点 xx 和非叶节点 yy ,问一次 root,x,yroot,x,y 可以知道 yy 是不是 xx 的祖先。
将每个非叶节点按照子树大小排序之后可以知道所有边了。
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 105; vector <int> lef, oth, seq, adj ; int n, rot, siz , par ; bool plc , anc ; inline int Query() { int cnt = 0, ret = 0; for (int i = 1; i <= n; ++i) { if (plc[i]) { ++cnt; } } printf("? %d", cnt); for (int i = 1; i <= n; ++i) { if (plc[i]) { printf(" %d", i); } } putchar(10); fflush(stdout); Read(ret); return ret; } inline int DFS(int x) { for (auto y : adj[x]) { if (y != par[x]) { par[y] = x, DFS(y); } } } int main() { #ifdef wxh010910 #endif Read(n); if (n == 2) { puts("! 1"); fflush(stdout); return 0; } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { plc[j] = i != j; } if (Query() == n - 1) { if (!rot) { rot = i; } else { lef.pb(i); } } else { oth.pb(i); } } for (auto x : lef) { for (auto y : oth) { for (int i = 1; i <= n; ++i) { plc[i] = i == rot || i == x || i == y; } if (Query() == 3) { anc[x][y] = true, ++siz[y]; } } } for (auto x : lef) { seq.clear(); for (int i = 1; i <= n; ++i) { if (anc[x][i]) { seq.pb(i); } } sort(seq.begin(), seq.end(), [&](const int &x, const int &y) { return siz[x] < siz[y]; }); par[x] = seq[0], par[seq.back()] = rot; for (int i = 1; i < seq.size(); ++i) { par[seq[i - 1]] = seq[i]; } } for (int i = 1; i <= n; ++i) { if (i != rot) { adj[par[i]].pb(i), adj[i].pb(par[i]), par[i] = 0; } } DFS(1), putchar('!'); for (int i = 2; i <= n; ++i) { printf(" %d", par[i]); } putchar(10); fflush(stdout); #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Prefix-free Queries:
预处理后缀数组,每次询问按字典序排序之后可以建出树,树形DP即可。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 400005; const int M = 20; int n, m, q, mod, top, g , h , L , arr , siz , sta , rnk , f[M] ; vector <int> adj ; char s ; inline void Build() { static int a , b , t , cnt_a , cnt_b ; for (int i = 1; i <= n; ++i) { ++cnt_a[s[i]]; } for (int i = 1; i < 26; ++i) { cnt_a[i] += cnt_a[i - 1]; } for (int i = n; i; --i) { arr[cnt_a[s[i]]--] = i; } rnk[arr[1]] = 1; for (int i = 2; i <= n; ++i) { rnk[arr[i]] = rnk[arr[i - 1]] + (s[arr[i]] != s[arr[i - 1]]); } for (int l = 1; rnk[arr ] < n; l <<= 1) { for (int i = 0; i <= n; ++i) { cnt_a[i] = cnt_b[i] = 0; } for (int i = 1; i <= n; ++i) { ++cnt_a[a[i] = rnk[i]], ++cnt_b[b[i] = i + l > n ? 0 : rnk[i + l]]; } for (int i = 1; i <= n; ++i) { cnt_a[i] += cnt_a[i - 1], cnt_b[i] += cnt_b[i - 1]; } for (int i = n; i; --i) { t[cnt_b[b[i]]--] = i; } for (int i = n; i; --i) { arr[cnt_a[a[t[i]]]--] = t[i]; } rnk[arr[1]] = 1; for (int i = 2; i <= n; ++i) { rnk[arr[i]] = rnk[arr[i - 1]] + (a[arr[i]] != a[arr[i - 1]] || b[arr[i]] != b[arr[i - 1]]); } } for (int i = 1, j = 0; i <= n; ++i) { for (j -= j > 0; rnk[i] != 1 && s[i + j] == s[arr[rnk[i] - 1] + j]; ++j); h[rnk[i]] = j; } } inline int LCP(int x, int y) { if (x == y) { return n - x + 1; } x = rnk[x], y = rnk[y]; if (x > y) { swap(x, y); } ++x; int k = L[y - x]; return min(f[k][x], f[k][y - (1 << k) + 1]); } struct String { int l, r; bool operator < (const String &b) const { int lcp = min(min(r - l + 1, b.r - b.l + 1), LCP(l, b.l)); if (b.r - b.l + 1 == lcp) { return false; } else if (r - l + 1 == lcp) { return true; } else { return s[l + lcp] < s[b.l + lcp]; } } bool operator == (const String &b) const { return r - l + 1 == b.r - b.l + 1 && LCP(l, b.l) >= r - l + 1; } } str ; inline bool Prefix(String a, String b) { return a.r - a.l + 1 == min(min(a.r - a.l + 1, b.r - b.l + 1), LCP(a.l, b.l)); } inline void DFS(int x) { g[x] = 1; for (auto y : adj[x]) { DFS(y), g[x] = 1LL * g[x] * (g[y] + 1) % mod; } g[x] = (g[x] + siz[x] - 1) % mod; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n), Read(q), siz[0] = 1; scanf("%s", s + 1), s[n + 1] = 26; for (int i = 1; i <= n; ++i) { s[i] -= 'a'; } Build(); for (int i = 1; i <= n; ++i) { f[0][i] = h[i]; } for (int j = 1; j < M; ++j) { for (int i = 1; i + (1 << j) - 1 <= n; ++i) { f[j][i] = min(f[j - 1][i], f[j - 1][i + (1 << j - 1)]); } } for (int i = 2; i <= n; ++i) { L[i] = L[i >> 1] + 1; } for (int i = 1; i <= q; ++i) { Read(m), Read(mod); for (int i = 1; i <= m; ++i) { Read(str[i].l), Read(str[i].r); } sort(str + 1, str + m + 1); sta[top = 1] = 1; for (int i = 2; i <= m; ++i) { if (!(str[i] == str[i - 1])) { sta[++top] = i; } } for (int i = 1; i <= top; ++i) { siz[i] = i == top ? m - sta[i] + 1 : sta[i + 1] - sta[i]; } m = top; for (int i = 1; i <= m; ++i) { str[i] = str[sta[i]]; } top = 0; for (int i = 0; i <= m; ++i) { adj[i].clear(); } for (int i = 1; i <= m; ++i) { for (; top && !Prefix(str[sta[top]], str[i]); --top); adj[sta[top]].pb(i), sta[++top] = i; } DFS(0); printf("%d\n", g[0]); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Subsequence Sum Queries:
分治,每次处理跨过 [mid,mid+1][mid,mid+1] 的答案,预处理背包即可。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 200005; const int M = 25; const int mod = 1e9 + 7; struct Node { int l, r, i; } s , t ; int n, m, q, a , ans , f [M]; inline void Solve(int l, int r, int ql, int qr) { if (ql > qr) { return ; } if (l == r) { for (int i = ql; i <= qr; ++i) { ans[s[i].i] = (!a[l]) + 1; } return ; } int mid = l + r >> 1, tl = ql - 1, tr = qr + 1; for (int j = 0; j < m; ++j) { f[mid][j] = (!j) + (j == a[mid]); f[mid + 1][j] = (!j) + (j == a[mid + 1]); } for (int i = mid - 1; i >= l; --i) { for (int j = 0; j < m; ++j) { f[i][j] = f[i + 1][j]; } for (int j = 0; j < m; ++j) { f[i][(j + a[i]) % m] = (f[i][(j + a[i]) % m] + f[i + 1][j]) % mod; } } for (int i = mid + 2; i <= r; ++i) { for (int j = 0; j < m; ++j) { f[i][j] = f[i - 1][j]; } for (int j = 0; j < m; ++j) { f[i][(j + a[i]) % m] = (f[i][(j + a[i]) % m] + f[i - 1][j]) % mod; } } for (int i = ql; i <= qr; ++i) { if (s[i].l <= mid && s[i].r > mid) { for (int j = 0; j < m; ++j) { ans[s[i].i] = (1LL * f[s[i].l][j] * f[s[i].r][(m - j) % m] + ans[s[i].i]) % mod; } } else if (s[i].r <= mid) { t[++tl] = s[i]; } else { t[--tr] = s[i]; } } for (int i = ql; i <= tl; ++i) { s[i] = t[i]; } for (int i = tr; i <= qr; ++i) { s[i] = t[i]; } Solve(l, mid, ql, tl), Solve(mid + 1, r, tr, qr); } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n), Read(m); for (int i = 1; i <= n; ++i) { Read(a[i]), a[i] %= m; } Read(q); for (int i = 1; i <= q; ++i) { Read(s[i].l), Read(s[i].r), s[i].i = i; } Solve(1, n, 1, q); for (int i = 1; i <= q; ++i) { printf("%d\n", ans[i]); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Consistent Occurrences:
本质不同的长度只有根号个,对于每种长度将哈希值存下来,询问直接查询。#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 100005; const int bas[2] = {2333, 2339}; const int mod[2] = {1000000007, 1000000009}; int n, m, all, cur, l , r , ans , len , h[2] , pwd[2] ; map <pii, pii> cnt; char s , t ; inline void Solve(int len) { cnt.clear(); for (int i = len; i <= n; ++i) { pii val = mp((h[0][i] - 1LL * h[0][i - len] * pwd[0][len] % mod[0] + mod[0]) % mod[0], (h[1][i] - 1LL * h[1][i - len] * pwd[1][len] % mod[1] + mod[1]) % mod[1]); if (cnt.find(val) == cnt.end()) { cnt[val] = mp(1, i); } else { if (i - cnt[val].Y < len) { continue; } else { ++cnt[val].X, cnt[val].Y = i; } } } for (int i = 1; i <= m; ++i) { if (r[i] - l[i] + 1 == len) { pii cur = mp(0, 0); for (int j = l[i]; j <= r[i]; ++j) { cur = mp((1LL * cur.X * bas[0] + t[j]) % mod[0], (1LL * cur.Y * bas[1] + t[j]) % mod[1]); } ans[i] = cnt[cur].X; } } } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n), Read(m); scanf("%s", s + 1); pwd[0][0] = pwd[1][0] = 1; for (int j = 0; j < 2; ++j) { for (int i = 1; i <= n; ++i) { h[j][i] = (1LL * h[j][i - 1] * bas[j] + s[i]) % mod[j]; pwd[j][i] = 1LL * pwd[j][i - 1] * bas[j] % mod[j]; } } for (int i = 1; i <= m; ++i) { scanf("%s", t + cur + 1); l[i] = cur + 1, len[i] = strlen(t + cur + 1); cur += len[i], r[i] = cur; } sort(len + 1, len + m + 1), all = unique(len + 1, len + m + 1) - len - 1; for (int i = 1; i <= all; ++i) { Solve(len[i]); } for (int i = 1; i <= m; ++i) { printf("%d\n", ans[i]); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
Increasing Costs:
建出最短路DAG,就是询问删掉一条边 11 不能到几个点。将边拆点,建出灭绝树,就是询问子树点数。
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 400005; const int M = 20; struct Edge { int p, v, w, i; } e[N << 1]; int n, m, ql, qr, e_cnt, d , q , ans , dep , hed , f[M] ; vector <int> adj ; inline void Dijkstra() { priority_queue <pair <LL, int>> q; static bool vis ; static LL dis ; for (int i = 1; i <= n; ++i) { dis[i] = LLONG_MAX; } dis[1] = 0, q.push(mp(0, 1)); while (!q.empty()) { int x = q.top().Y; q.pop(); if (vis[x]) { continue; } for (int i = hed[x]; i; i = e[i].v) { if (CheckMin(dis[e[i].p], dis[x] + e[i].w)) { q.push(mp(-dis[e[i].p], e[i].p)); } } } for (int x = 1; x <= n; ++x) { for (int i = hed[x]; i; i = e[i].v) { if (dis[e[i].p] == dis[x] + e[i].w) { adj[e[i].p + m].pb(e[i].i); adj[e[i].i].pb(x + m); ++d[e[i].i], ++d[x + m]; } } } } inline int LCA(int x, int y) { if (dep[x] < dep[y]) { swap(x, y); } if (dep[x] != dep[y]) { for (int i = 0; i < M; ++i) { if (dep[x] - dep[y] >> i & 1) { x = f[i][x]; } } } if (x == y) { return x; } for (int i = M - 1; ~i; --i) { if (f[i][x] != f[i][y]) { x = f[i][x], y = f[i][y]; } } return f[0][x]; } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n), Read(m); for (int i = 1, u, v, w; i <= m; ++i) { Read(u), Read(v), Read(w); e[++e_cnt] = {v, hed[u], w, i}, hed[u] = e_cnt; e[++e_cnt] = {u, hed[v], w, i}, hed[v] = e_cnt; } Dijkstra(); for (int i = m + 1; i <= n + m; ++i) { if (!d[i]) { q[++qr] = i; } } while (ql <= qr) { int x = q[++ql]; for (auto y : adj[x]) { if (!--d[y]) { q[++qr] = y; } } } for (int i = qr - 1; i; --i) { int x = q[i], cur = adj[x][0]; for (auto y : adj[x]) { cur = LCA(cur, y); } f[0][x] = cur, dep[x] = dep[cur] + 1; for (int j = 1; j < M; ++j) { f[j][x] = f[j - 1][f[j - 1][x]]; } } for (int i = 1; i < qr; ++i) { int x = q[i]; ans[x] += x > m; ans[f[0][x]] += ans[x]; } for (int i = 1; i <= m; ++i) { printf("%d\n", ans[i]); } #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }
相关文章推荐
- CodeForces Gym 101745 简要题解
- Codeforces GYM 100646E: Su-Su-Sudoku 题解
- CodeForces Gym 101615简要题解
- Codeforces Round #398 (div.2)简要题解
- Codeforces #306 Div 2 简要题解
- CodeForces Gym 101190简要题解
- CodeForces Gym 101620简要题解
- [Codeforces Gym]2015年ACM-ICPC越南国赛第二场简要题解
- Codeforces #274 Div 1 简要题解
- CodeForces Gym 101630简要题解
- 【二分】NEERC15 L Landscape Improved(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
- Codeforces Gym 101234E Lines Game
- Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)
- Codeforces Gym 101190 (NEERC 2016) E. Expect to Wait (扫描线)
- codeforces gym 100286 I iSharp (字符串模拟)
- codeforces gym 100694 M The Fifth Season (巴什博奕)
- Codeforces Gym 101484 K Counting Good Teams
- 【codeforces #282(div 1)】AB题解
- Codeforces Gym 101173 K. Key Knocking (构造)
- Mr. Kitayuta's Technology CodeForces - 505D(并查集+拓扑排序或dfs找环) 题解