20260724 - 暑期部分分训练 1
A - 方差
欸,正解是 SA?
24pts
爆搜就好了。
void dfs(const vector<int> &now) {
cnt.insert(now);
ll res = [&](const vector<int> &k) -> ll{
ll sqr = 0, sum = 0;
for (auto i : k) sqr += i * i, sum += i;
return n * sqr - sum * sum;
}(now);
ans = min(ans, res);
for (int i = 1; i < n - 1; i++) {
vector<int> t = now;
t[i] = t[i - 1] + t[i + 1] - t[i];
if (!cnt.count(t) || t[i] > ans)
dfs(t);
}
}
32pts
如果答案比他大的多,就一定不行,设置一个分界点。
void dfs(const vector<int> &now, ll sqr, ll sum) {
cnt[now] = true;
ll res = n * sqr - sum * sum;
if (res > 1.1 * ans) return;
ans = min(ans, res);
for (int i = 1; i < n - 1; i++) {
vector<int> t = now;
t[i] = t[i - 1] + t[i + 1] - t[i];
if (cnt.find(t) == cnt.end()) {
ll sq = sqr - now[i] * now[i] + t[i] * t[i], su = sum - now[i] + t[i];
ll ret = n * sq - su * su;
if (ret > 1.09 * ans) continue;
dfs(t, sq, su);
}
}
}
正解是 SA?我要去学一下。
使用 A* 失败了。
B - 归程
30pts
跑一边 Dijkstra 就好了,注意有一个点 \(Q = 0\)?打 freopen 也能拿到 \(5pts\) 哈哈哈。
namespace sub1 {
void solve() {
dijkstra(1);
scanf("%d%d%d", &Q, &K, &S);
while (Q--) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
if (h < adj[1][0][2]) {
printf("%d\n", 0); lastans = 0;
} else {
lastans = dis[v];
printf("%d\n", dis[v]);
}
}
}
};
55pts
因为树上路径唯一,所以直接树上倍增求最小值,然后判断是否能走,然后就没了。
namespace sub2 {
int fa[N][21], minv[N][21];
void dfs(int u, int from) {
for (auto nxt : adj[u]) {
int v = nxt[0], w = nxt[2];
if (v == from) continue;
fa[v][0] = u;
minv[v][0] = w;
dfs(v, u);
}
}
int getfa(int u, int t) {
if (!t) return 1;
for (int i = 20; i >= 0; i--) {
if (minv[u][i] > t) u = fa[u][i];
}
return u;
}
void solve() {
dfs(1, 0);
dijkstra(1);
for (int j = 1; j <= 20; j++) {
for (int i = 1; i <= n; i++) {
fa[i][j] = fa[fa[i][j - 1]][j - 1];
minv[i][j] = min(minv[i][j - 1], minv[fa[i][j - 1]][j - 1]);
}
}
scanf("%d%d%d", &Q, &K, &S);
while (Q--) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
lastans = dis[getfa(v, h)];
printf("%d\n", lastans);
}
for (int j = 1; j <= 20; j++) {
for (int i = 1; i <= n; i++) {
fa[i][j] = minv[i][j] = 0;
}
}
}
};
70pts
从大到小排序,然后直接乱搞。
if (K == 0) {
dijkstra(1);
vector<int> ans(Q + 1);
vector<array<int, 3>> q;
for (int i = 1; i <= Q; i++) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
q.push_back({h, v, i});
}
sort(all(q), [&](const AR3 &A, const AR3 &B) {
return A[0] > B[0];
});
sort(all(edge), [&](const array<int, 4> &A, const array<int, 4> &B) {
return A[0] > B[0];
});
vector<int> fa(n + 1); iota(all(fa), 0);
auto find = [&](auto &self, int x) -> int {
if (fa[x] == x) return x;
return fa[x] = self(self, fa[x]);
};
auto merge = [&](int u, int v) -> void {
int uf = find(find, u), vf = find(find, v);
if (uf == vf) return;
if (dis[uf] < dis[vf]) fa[vf] = uf;
else fa[uf] = vf;
};
int idx = 0;
for (auto [h, v, id] : q) {
while (idx < m && h < edge[idx][0]) {
auto [a, x, y, l] = edge[idx];
merge(x, y);
++idx;
}
ans[id] = dis[find(find, v)];
}
for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
}
80pts
直接爆搜就好了。
if (n <= 1500) {
dijkstra(1);
for (int i = 1; i <= Q; i++) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
vector<int> vis(n + 1); int ans = inf;
auto dfs = [&](auto &self, int u) -> void {
if (vis[u]) return;
vis[u] = true;
ans = min(ans, dis[u]);
for (auto [vc, l, a] : adj[u]) {
if (a > h) self(self, vc);
}
};
dfs(dfs, v);
printf("%d\n", lastans = ans);
}
完整奇葩码风代码:
#include <bits/stdc++.h>
using namespace std;
#define AKCoder
#ifdef AKCoder
template<class t,class u>ostream& operator<<(ostream& os,const pair<t,u>& p){return os<<"("<<p.first<<","<<p.second<<")";}
#define debug(x) cout<<#x<<" = "<<(x)<<'\n'
#else
#define debug(x);
#endif
#define ll long long
#define ull unsigned long long
#define db double
#define all(x) (x).begin(), (x).end()
#define inf (1 << 30)
#define lnf (1LL << 60)
typedef pair<int, int> PII;
typedef array<int, 3> AR3;
constexpr int N = 200000 + 7;
constexpr int P = 998244353;
int n, m;
int Q, K, S, lastans;
vector<array<int, 3>> adj[N];
int dis[N];
bool vis[N];
void dijkstra(int s) {
priority_queue<AR3, vector<AR3>, greater<AR3>> q;
memset(dis, 0x3f, sizeof(dis));
memset(vis, false, sizeof(vis));
dis[s] = 0;
q.push({0, s});
while (!q.empty()) {
int u = q.top()[1]; q.pop();
if (vis[u]) continue; vis[u] = true;
for (auto nxt : adj[u]) {
int v = nxt[0], w = nxt[1];
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
}
void clearT() {
lastans = 0;
for (int i = 1; i <= n; i++) adj[i].clear();
}
namespace sub1 {
void solve() {
dijkstra(1);
scanf("%d%d%d", &Q, &K, &S);
while (Q--) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
if (h < adj[1][0][2]) {
printf("%d\n", 0); lastans = 0;
} else {
lastans = dis[v];
printf("%d\n", dis[v]);
}
}
}
};
namespace sub2 {
int fa[N][21], minv[N][21];
void dfs(int u, int from) {
for (auto nxt : adj[u]) {
int v = nxt[0], w = nxt[2];
if (v == from) continue;
fa[v][0] = u;
minv[v][0] = w;
dfs(v, u);
}
}
int getfa(int u, int t) {
if (!t) return 1;
for (int i = 20; i >= 0; i--) {
if (minv[u][i] > t) u = fa[u][i];
}
return u;
}
void solve() {
dfs(1, 0);
dijkstra(1);
for (int j = 1; j <= 20; j++) {
for (int i = 1; i <= n; i++) {
fa[i][j] = fa[fa[i][j - 1]][j - 1];
minv[i][j] = min(minv[i][j - 1], minv[fa[i][j - 1]][j - 1]);
}
}
scanf("%d%d%d", &Q, &K, &S);
while (Q--) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
lastans = dis[getfa(v, h)];
printf("%d\n", lastans);
}
for (int j = 1; j <= 20; j++) {
for (int i = 1; i <= n; i++) {
fa[i][j] = minv[i][j] = 0;
}
}
}
};
void solve() {
bool markH = true;
int sameH = -1;
clearT();
scanf("%d%d", &n, &m);
vector<array<int, 4>> edge;
for (int i = 1; i <= m; i++) {
int u, v, l, a;
scanf("%d%d%d%d", &u, &v, &l, &a);
edge.push_back({a, u, v, l});
if (sameH == -1) sameH = a;
else if (sameH != a) markH = false;
adj[u].push_back({v, l, a});
adj[v].push_back({u, l, a});
}
if (markH) sub1::solve();
else if (n == m + 1) sub2::solve();
else {
scanf("%d%d%d", &Q, &K, &S);
if (K == 0) {
dijkstra(1);
vector<int> ans(Q + 1);
vector<array<int, 3>> q;
for (int i = 1; i <= Q; i++) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
q.push_back({h, v, i});
}
sort(all(q), [&](const AR3 &A, const AR3 &B) {
return A[0] > B[0];
});
sort(all(edge), [&](const array<int, 4> &A, const array<int, 4> &B) {
return A[0] > B[0];
});
vector<int> fa(n + 1); iota(all(fa), 0);
auto find = [&](auto &self, int x) -> int {
if (fa[x] == x) return x;
return fa[x] = self(self, fa[x]);
};
auto merge = [&](int u, int v) -> void {
int uf = find(find, u), vf = find(find, v);
if (uf == vf) return;
if (dis[uf] < dis[vf]) fa[vf] = uf;
else fa[uf] = vf;
};
int idx = 0;
for (auto [h, v, id] : q) {
while (idx < m && h < edge[idx][0]) {
auto [a, x, y, l] = edge[idx];
merge(x, y);
++idx;
}
ans[id] = dis[find(find, v)];
}
for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
} else if (n <= 1500) {
dijkstra(1);
for (int i = 1; i <= Q; i++) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
vector<int> vis(n + 1); int ans = inf;
auto dfs = [&](auto &self, int u) -> void {
if (vis[u]) return;
vis[u] = true;
ans = min(ans, dis[u]);
for (auto [vc, l, a] : adj[u]) {
if (a > h) self(self, vc);
}
};
dfs(dfs, v);
printf("%d\n", lastans = ans);
}
}
}
}
int main() {
int oT_To = 1;
scanf("%d", &oT_To);
while (oT_To--) solve();
return 0;
}
100pts
跑 Kruskal 重构树就好了。
#include <bits/stdc++.h>
using namespace std;
#define AKCoder
#ifdef AKCoder
template<class t,class u>ostream& operator<<(ostream& os,const pair<t,u>& p){return os<<"("<<p.first<<","<<p.second<<")";}
#define debug(x) cout<<#x<<" = "<<(x)<<'\n'
#else
#define debug(x);
#endif
#define ll long long
#define ull unsigned long long
#define db double
#define all(x) (x).begin(), (x).end()
#define inf (1 << 30)
#define lnf (1LL << 60)
typedef pair<int, int> PII;
typedef array<int, 3> AR3;
constexpr int N = 400000 + 7;
constexpr int P = 998244353;
struct Node {
int v, l, a;
};
struct Edge {
int u, v, l, a;
bool operator < (const Edge &A) const {
return a > A.a;
}
};
int n, m;
int Q, K, S, lastans;
vector<int> adj[N];
vector<Node> graph[N];
vector<Edge> edge;
int dis[N];
bool vis[N];
void dijkstra(int s) {
priority_queue<AR3, vector<AR3>, greater<AR3>> q;
memset(dis, 0x3f, sizeof(dis));
memset(vis, false, sizeof(vis));
dis[s] = 0;
q.push({0, s});
while (!q.empty()) {
int u = q.top()[1]; q.pop();
if (vis[u]) continue; vis[u] = true;
for (auto [v, w, _] : graph[u]) {
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
}
int fa[N], val[N], f[N][20], cnt, leaf[N];
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void ex_kruskal() {
sort(all(edge));
cnt = n;
for (int i = 1; i <= n * 2; i++) fa[i] = i;
for (auto [u, v, l, a] : edge) {
int uf = find(u), vf = find(v);
if (uf != vf) {
fa[uf] = fa[vf] = ++cnt;
val[cnt] = a;
adj[uf].push_back(cnt), adj[cnt].push_back(uf);
adj[vf].push_back(cnt), adj[cnt].push_back(vf);
}
}
}
void dfs(int u, int from) {
for (auto v : adj[u]) {
if (v == from) continue;
f[v][0] = u;
dfs(v, u);
leaf[u] = min(leaf[u], leaf[v]);
}
leaf[u] = min(leaf[u], dis[u]);
}
int half_lca(int u, int p) {
for (int i = 19; i >= 0; i--) {
if (val[f[u][i]] > p) u = f[u][i];
}
return u;
}
void clearT() {
cnt = 0;
lastans = 0;
edge.clear();
memset(leaf, 0x3f, sizeof(leaf));
for (int i = 1; i <= n * 2; i++) adj[i].clear(), graph[i].clear();
}
void solve() {
clearT();
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v, l, a;
scanf("%d%d%d%d", &u, &v, &l, &a);
graph[u].push_back({v, l, a});
graph[v].push_back({u, l, a});
edge.push_back({u, v, l, a});
}
dijkstra(1);
ex_kruskal();
dfs(cnt, 0);
for (int j = 1; j <= 19; j++)
for (int i = 1; i <= cnt; i++)
f[i][j] = f[f[i][j - 1]][j - 1];
scanf("%d%d%d", &Q, &K, &S);
while (Q--) {
int v0, p0, v, h;
scanf("%d%d", &v0, &p0);
v = (v0 + K * lastans - 1) % n + 1;
h = (p0 + K * lastans) % (S + 1);
int pos = half_lca(v, h);
printf("%d\n", lastans = leaf[pos]);
}
}
int main() {
// freopen("return.out", "w", stdout);
int oT_To = 1;
scanf("%d", &oT_To);
while (oT_To--) solve();
return 0;
}

浙公网安备 33010602011771号