int n, m; string s; int cnt[26], pos[26][100005], id[100005]; int le[26][100005], ri[26][100005]; int sg[26][100005], pre[26][100005], suf[26][100005]; vector<pair<int, int>> v;
intquery1(int l, int r){ int res = 0; for (int i = 0; i < 26; i++) { int ll = ri[i][l], rr = le[i][r]; if (ll > rr) continue; int now = 0; for (int j = id[ll] + 1; j <= id[rr]; j++) now ^= sg[i][j]; if (l < ll) { if (suf[i][l] == -1) suf[i][l] = query1(l, ll - 1); now ^= suf[i][l]; } if (rr < r) { if (pre[i][r] == -1) pre[i][r] = query1(rr + 1, r); now ^= pre[i][r]; } if (now < 26) res |= 1 << now; } for (int i = 0; i < 26; i++) if ((res >> i & 1) == 0) return i; return26; } intquery2(int l, int r){ int res = 0; for (int i = 0; i < 26; i++) { int ll = ri[i][l], rr = le[i][r]; if (ll > rr) continue; int now = sg[i][id[rr]] ^ sg[i][id[ll]]; if (l < ll) { if (suf[i][l] == -1) suf[i][l] = query2(l, ll - 1); now ^= suf[i][l]; } if (rr < r) { if (pre[i][r] == -1) pre[i][r] = query2(rr + 1, r); now ^= pre[i][r]; } if (now < 26) res |= 1 << now; } for (int i = 0; i < 26; i++) if ((res >> i & 1) == 0) return i; return26; }
intmain(){ cin >> s; n = s.length(); s = " " + s; for (int i = 1; i <= n; i++) pos[s[i] - 'a'][id[i] = ++cnt[s[i] - 'a']] = i; for (int i = 0; i < 26; i++) { le[i][0] = 0; for (int j = 1; j <= n; j++) le[i][j] = s[j] - 'a' == i ? j : le[i][j - 1]; } for (int i = 0; i < 26; i++) { ri[i][n + 1] = n + 1; for (int j = n; j >= 1; j--) ri[i][j] = s[j] - 'a' == i ? j : ri[i][j + 1]; } for (int i = 0; i < 26; i++) for (int j = 2; j <= cnt[i]; j++) if (pos[i][j - 1] + 1 != pos[i][j]) v.emplace_back(pos[i][j - 1], pos[i][j]); sort(v.begin(), v.end(), [](const pair<int, int> &x, const pair<int, int> &y) { return x.second - x.first < y.second - y.first; }); memset(pre, -1, sizeof(pre)); memset(suf, -1, sizeof(suf)); for (auto now : v) sg[s[now.second] - 'a'][id[now.second]] = query1(now.first + 1, now.second - 1); for (int i = 0; i < 26; i++) for (int j = 1; j <= cnt[i]; j++) sg[i][j] ^= sg[i][j - 1]; scanf("%d", &m); while (m--) { int l, r; scanf("%d%d", &l, &r); puts(query2(l, r) ? "Alice" : "Bob"); } return0; }
int n, k, sq, a[300005], p[300005]; longlong ans; structquery {int id, l, r; longlong ans;} q[300005]; int b[300005], num[300005], vis[300005], idx, c[300005];
longlongcalc(longlong a, longlong b, longlong k){ return k * a * a + a * b * k * k - a * b * k + b * b * (k * (k - 1) * (2 * k - 1)/6); } voidupdate(int x){if (!vis[x]) vis[x] = 1, c[++idx] = x;} voidadd(int x){num[b[x]]--; b[x]++; num[b[x]]++; update(b[x]); return ;} voiddel(int x){num[b[x]]--; b[x]--; if (b[x]) num[b[x]]++, update(b[x]); return ;}
longlongcalc(longlong tot, longlong l, longlong x, longlong c){ return c * (c + 1) * (c * 2 + 1) / 6 * x * x + l * c * (c + 1) * x + l * l * c + c * (c + 1) * (c * 2 + 1) / 6 * x * x + (tot - l - x * c) * c * (c + 1) * x + (tot - l - x * c) * (tot - l - x * c) * c; }
intmain(){ ios::sync_with_stdio(0); cin.tie(0); cin >> n >> k; for (int i = 1; i <= n; i++) cin >> a[i]; sq = sqrt(n); for (int i = 1; i <= n; i++) p[i] = (i - 1) / sq + 1; for (int i = 1; i <= k; i++) cin >> q[i].l >> q[i].r, q[i].id = i; sort(q + 1, q + k + 1, [](const query &x, const query &y) { return p[x.l] != p[y.l] ? p[x.l] < p[y.l] : (p[x.l] % 2 ? x.r < y.r : x.r > y.r); }); for (int i = 1, l = 1, r = 0; i <= k; i++) { while (l > q[i].l) add(a[--l]); while (r < q[i].r) add(a[++r]); while (l < q[i].l) del(a[l++]); while (r > q[i].r) del(a[r--]); int _idx = 0; for (int j = 1; j <= idx; j++) { vis[c[j]] = 0; if (num[c[j]]) c[++_idx] = c[j]; } idx = _idx; sort(c + 1, c + idx + 1); for (int j = 1; j <= idx; j++) vis[c[j]] = 1; int len = r - l + 1, cnt = 0, _num[] = {0, 0}, lr = 0; longlong res = 0; for (int j = 1; j <= idx; j++) { int tmp = c[j]; cnt += num[tmp]; res += calc(len, _num[lr], tmp, num[tmp] / 2) + calc(len, _num[lr ^ 1], tmp, (num[tmp] + 1) / 2); _num[lr] += tmp * (num[tmp] / 2); _num[lr ^ 1] += tmp * ((num[tmp] + 1) / 2); if (num[tmp] % 2 == 1) lr ^= 1; } q[i].ans = ((longlong)cnt * len * (len + 1) - (longlong)len * (cnt - 1) - res + (2ll * len * len)) / 2; } sort(q + 1, q + k + 1, [](const query &x, const query &y) { return x.id < y.id; }); for (int i = 1; i <= k; i++) cout << q[i].ans << '\n'; return0; }
intmain(){ scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); a[x]++; } for (int i = 0; i < (1 << k); i++) if (!a[i]) v.emplace_back(i, i, 1e9, -1e9); else v.emplace_back(i, i, i, i); solve(0, 0, v, 1e9); for (int i = 0; i < (1 << k); i++) printf("%d ", ans[i]); puts(""); return0; }
int n, d[500005], f[500005], in[500005]; structgraph { int tot, hd[500005]; int nxt[1000005], to[1000005];
voidadd(int u, int v){ nxt[++tot] = hd[u]; hd[u] = tot; to[tot] = v; return ; } } tr, g; priority_queue<int, vector<int>, greater<int>> q; int idx, ans[500005];
voiddfs(int now, int fa){ for (int i = tr.hd[now]; i; i = tr.nxt[i]) if (tr.to[i] != fa) dfs(tr.to[i], now); if (!f[now]) { if (f[fa]) { cout << "-1\n"; exit(0); } for (int i = tr.hd[now]; i; i = tr.nxt[i]) if (tr.to[i] != fa) g.add(fa, tr.to[i]), in[tr.to[i]]++; for (int i = tr.hd[fa]; i; i = tr.nxt[i]) if (tr.to[i] != now) g.add(now, tr.to[i]), in[tr.to[i]]++; f[now] = f[fa] = 1; } return ; }
intmain(){ ios::sync_with_stdio(0); cin.tie(0); cin >> n; for (int i = 1; i < n; i++) { int u, v; cin >> u >> v; tr.add(u, v); tr.add(v, u); d[u]++, d[v]++; } if (n == 1) { cout << "-1\n"; return0; } if (n == 2) { cout << "1 2\n"; return0; } if (n % 2 == 1) { cout << "-1\n"; return0; } int rt = 1; for (int i = 1; i <= n; i++) if (d[i] >= 2) rt = i; f[0] = 1; dfs(rt, 0); for (int i = 1; i <= n; i++) if (!in[i]) q.push(i); while (!q.empty()) { int now = q.top(); q.pop(); ans[++idx] = now; for (int i = g.hd[now]; i; i = g.nxt[i]) if (!--in[g.to[i]]) q.push(g.to[i]); } for (int i = 1; i <= n; i++) cout << ans[i] << ' '; cout << '\n'; return0; }
CF1348F Phoenix and Memory [**]
考虑把限制视为区间,相当于要求每个区间对应一个其内部的点。
按左端点排序,每次将当前点给一个右端点最小的点,即可求出一组合法解。
考虑能否求出第二组解。
结论:如果有合法解,一定有一组可以通过交换当前解的某两个数得到。
考虑反证。假设必须要进行一个大于 2 的置换得到一个合法的排列,假设其最靠左的点为 x,将 x 置换到 y,将 z 置换到 x。
int n, p[200005]; structinterval { int id, l, r, p; } a[200005]; vector<int> v[200005]; set<pair<int, int>> s; int ans[2][200005];
intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].l, &a[i].r), p[i] = i, v[a[i].l].push_back(i); for (int i = 1; i <= n; i++) { for (int j : v[i]) s.emplace(a[j].r, j); a[s.begin()->second].p = i; s.erase(s.begin()); } for (int i = 1; i <= n; i++) ans[0][i] = ans[1][i] = a[i].p; sort(p + 1, p + n + 1, [](constint &x, constint &y) { return a[x].p < a[y].p; }); set<pair<int, int>>().swap(s); int flag = 0; for (int i = 1; i <= n; i++) { for (int j : v[a[p[i]].p]) s.emplace(a[j].p, j); if (s.upper_bound(make_pair(a[p[i]].p, 0)) != s.end()) { auto it = s.upper_bound(make_pair(a[p[i]].p, 0)); if (it->second == p[i]) it = next(it); if (it == s.end()) continue; auto tmp = *it; if (tmp.first <= a[p[i]].r) { swap(ans[1][tmp.second], ans[1][p[i]]); flag = 1; break; } } } if (!flag) { puts("YES"); for (int i = 1; i <= n; i++) printf("%d ", ans[0][i]); puts(""); } else { puts("NO"); for (int i = 1; i <= n; i++) printf("%d ", ans[0][i]); puts(""); for (int i = 1; i <= n; i++) printf("%d ", ans[1][i]); puts(""); } return0; }
// for (int i = 1; i <= 2 * n; i++) printf("%d %d %d %d\n", b[i].op, b[i].x, b[i].y, b[i].id);
memset(tr.w, 0, sizeof(tr.w)); longlong ans = 0;
for (int i = 1; i <= 2 * n; i++) if (!b[i].op) tr.update(b[i].y + 200001); else ans += (longlong)tr.query(b[i].y + 200001) * a[b[i].id][p[1]];
return ans; }
intmain(){ scanf("%d%d", &m, &n); for (int j = 1; j <= m; j++) for (int i = 1; i <= n; i++) scanf("%d", &a[i][j]);
if (m == 2) { for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) ans += a[i][j]; ans *= n * 2; printf("%lld\n", ans); return0; }
for (int i = 1; i <= m; i++) p[i] = i;
do { if (p[2] > p[3]) continue; for (int i = 1; i <= n; i++) b[i] = { 0, a[i][p[2]] - a[i][p[1]], a[i][p[3]] - a[i][p[1]], i }; for (int i = 1; i <= n; i++) b[n + i] = { 1, a[i][p[1]] - a[i][p[2]] - (p[1] > p[2]), a[i][p[1]] - a[i][p[3]] - (p[1] > p[3]), i }; ans += calc(); } while (next_permutation(p + 1, p + m + 1));
do { if (p[2] > p[3]) continue; for (int i = 1; i <= n; i++) b[i] = { 0, a[i][p[1]] - a[i][p[2]], a[i][p[1]] - a[i][p[3]], i }; for (int i = 1; i <= n; i++) b[n + i] = { 1, a[i][p[2]] - a[i][p[1]] - (p[1] > p[2]), a[i][p[3]] - a[i][p[1]] - (p[1] > p[3]), i }; // printf("Permutation: %d %d %d\n", p[1], p[2], p[3]); ans += calc(); // puts(""); } while (next_permutation(p + 1, p + m + 1)); // printf("%lld\n", ans);
if (m == 3) printf("%lld\n", ans * 2); else { for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) ans -= (longlong)a[i][j] * n; printf("%lld\n", ans); }
return0; }
POI2020-2021R3 Suma liczb pierwszych
牛牛题。
数据点分治,当 n 小的时候直接处理出所有质数然后双指针。
当 n 大的时候质数个数不会很大,枚举个数 k,然后毛咕咕在 kn 周围,于是在 kn 前后取 k 个质数双指针即可。取质数直接暴力枚举。