#include<bits/stdc++.h> usingnamespacestd; #define ll long long constint maxn = 2e5 + 10; constint mod = 1e9 + 7; string s; int pre0[maxn], pre1[maxn], pos1[maxn]; ll qpow(ll n, ll k){ ll ans = 1; while (k) { if (k & 1) ans = ans * n % mod; n = n * n % mod; k >>= 1; } return ans; } voidrun(){ cin >> s; int len = s.size(); for (int i = 0; i <= len; i++) pre1[i] = pre0[i] = pos1[i] = 0; for (int i = len - 1; i >= 0; i--) { if (s[i] == '1') { pre1[i] = pre1[i + 1] + 1; pre0[i] = pre0[i + 1]; } if (s[i] == '0') { pre0[i] = pre0[i + 1] + 1; pre1[i] = pre1[i + 1]; } } int num = 0; for (int i = 0; i < len; i++) { if (s[i] == '1') pos1[++num] = i; } ll ans = 1; for (int i = 1; i <= num; i++) { ll res = 1; res = res * qpow(3, pre1[pos1[i] + 1]) % mod * qpow(2, pre0[pos1[i] + 1]) % mod; ans = (ans + res) % mod; } printf("%lld\n", ans); }
intmain(){ int t; cin >> t; while (t--) run(); return0; }
#include<bits/stdc++.h> usingnamespacestd; #define ll long long constint N = 1e5 + 10; const ll mod = 998857459;
inlineintrd(){ int w = 0, f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); } while (isdigit(ch)) { w = w * 10 + ch - '0'; ch = getchar(); } return w * f; }
int n, m; ll maxx[N];
ll val[3005]; int b[3005], q; int a[N], len[3005], tot;
structNode { ll v; int len; booloperator<(const Node &a) const { if (v == a.v) return len < a.len; return v < a.v; } };
set<Node> st; set<Node>::iterator it;
intmain(){ n = rd(); m = rd(); val[1] = 1; for (int i = 2; i <= 2802; ++i) { val[i] = val[i - 1] * (ll)i % mod; } for (int i = 1; i <= n; ++i) { a[i] = rd(); maxx[i] = -1; } for (int i = 1; i <= n; ++i) { if (a[i] <= 2802) { b[++tot] = a[i]; len[tot] = 1; while (i < n && a[i + 1] > 2802) { len[tot]++; i++; } } } for (int i = tot; i >= 1; --i) { ll tmp = val[b[i]]; int l = 1; if (tmp > maxx[l]) { maxx[l] = tmp; } for (int j = i - 1; j >= 1; --j) { tmp = (tmp + val[b[j]]) % mod; l += len[j]; if (tmp > maxx[l]) { maxx[l] = tmp; } } } ll now = -1; for (int i = 1; i <= n; i++) { if (maxx[i] == -1) continue; if (now < maxx[i]) { st.insert({maxx[i], i}); now = maxx[i]; } } for (int i = 1; i <= m; ++i) { q = rd(); it = st.lower_bound({q, 0}); if (it != st.end()) printf("%d\n", it->len); else puts("-1"); } return0; }
接下来考虑如何减小时间复杂度。我们枚举点z做为LCA时,其实就是在以点z为根节点的子树上进行询问。因为x和y互相没有祖先关系,如果每次确定点x所在的链,询问之后再将这条链加入询问集合,就能直接避免出现这种情况,并且再将询问结果∗2就能得到有序对的答案,很像dsu on tree的过程,那么剖完大力合并就行了。
int n, k, tot, son; int w[N], dep[N], sz[N], bigSon[N]; int rt[N * 80], ls[N * 80], rs[N * 80], num[N * 80]; ll ans; vector<int> G[N];
voidmodify(int &id, int l, int r, int p, int v){ if (!id) id = ++tot; num[id] += v; if (l == r) return; int mid = l + r >> 1; if (p <= mid) modify(ls[id], l, mid, p, v); else modify(rs[id], mid + 1, r, p, v); }
intquery(int id, int l, int r, int ql, int qr){ if (l >= ql && r <= qr) return num[id]; int ans = 0; int mid = l + r >> 1; if (ql <= mid) ans += query(ls[id], l, mid, ql, qr); if (qr > mid) ans += query(rs[id], mid + 1, r, ql, qr); return ans; }
voiddfsSz(int u){ sz[u] = 1; for (auto v : G[u]) { dep[v] = dep[u] + 1; dfsSz(v); sz[u] += sz[v]; if (sz[v] > sz[bigSon[u]]) bigSon[u] = v; } }
voidadd(int u, int val){ modify(rt[w[u]], 1, n, dep[u], val); for (auto v : G[u]) { add(v, val); } }
voidcalc(int u, int fa){ int dv = 2 * dep[fa] + k - dep[u]; int wv = 2 * w[fa] - w[u]; dv = min(dv, n); if (dv >= 1 && wv >= 0 && wv <= n) ans += 2ll * (ll)query(rt[wv], 1, n, 1, dv); for (auto v : G[u]) { calc(v, fa); } }
voiddfs(int u){ for (auto v : G[u]) { if (v == bigSon[u]) continue; dfs(v); add(v, -1); } if (bigSon[u]) dfs(bigSon[u]);
for (auto v : G[u]) { if (v == bigSon[u]) continue; calc(v, u); add(v, 1); } modify(rt[w[u]], 1, n, dep[u], 1); }
voidsolve(){ cin >> n >> k; for (int i = 1; i <= n; ++i) { cin >> w[i]; } for (int i = 2, u; i <= n; ++i) { cin >> u; G[u].push_back(i); } dep[1] = 1; dfsSz(1); dfs(1); cout << ans << endl; }
intmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cout << fixed << setprecision(20); int t = 1; while (t--) solve(); return0; }