比赛链接
T1
100 pts。
思路
枚举左端点,二分右端点,时间 \(O(n \log n)\),比 std(\(O(100 \times n)\)) 优秀。
Code
#include <bits/stdc++.h>
#define int long longusing namespace std;const int kMaxN = 1e5 + 5, kM = 100;
int n, a[kMaxN], sum[kMaxN];signed main() {cin.tie(0)->sync_with_stdio(false);cin >> n;for (int i = 1; i <= n; ++i) {cin >> a[i];sum[i] = sum[i - 1] + a[i];}if (n <= 1000) {int mx = 0;for (int i = 1; i <= n; ++i) {for (int j = i; j <= n; ++j) {if (((sum[j] - sum[i - 1]) % kM + kM) % kM > mx) {mx = ((sum[j] - sum[i - 1]) % kM + kM) % kM;}}} cout << mx;return 0;}int mx = 0;for (int i = 1; i <= n; ++i) {int lt = i - 1, rt = n + 1, L = 0;for (int mid; lt + 1 < rt;) {mid = lt + rt >> 1;if (((sum[mid] - sum[i - 1]) % kM + kM) % kM < 100 && ((sum[mid] - sum[i - 1]) % kM + kM) % kM > L) {lt = mid;L = ((sum[mid] - sum[i - 1]) % kM + kM) % kM;} else {rt = mid;}}mx = max(mx, ((sum[lt] - sum[i - 1]) % kM + kM) % kM);}cout << mx;return 0;
}
T2
45 pts。
思路
一眼同余最短路。
错误
第一没判误解,第二跑反了。
Code
#include <bits/stdc++.h>
#define int long longusing namespace std;
using Pii = pair<int, int>;const int kMaxN = 1e5 + 5, kInf = 9e18;
int n, p, x, q, y, a[kMaxN], sum;
map<int, int> dis;
map<int, bool> vis;struct Node {int id, w;bool operator<(const Node& rhs) const {return w > rhs.w;}
};void dijkstra(int s) {priority_queue<Node> h;for (h.push({s, 0}), dis[s] = 0; !h.empty();) {Node u = h.top();h.pop();if (vis[u.id]) {continue; }vis[u.id] = 1;int v = (u.id + x) % n, w = p;if (!vis[v] && (!dis.count(v) || dis[v] > dis[u.id] + w)) {dis[v] = dis[u.id] + w;h.push({v, dis[v]});}v = (u.id - y) % n, w = q;if (!vis[v] && (!dis.count(v) || dis[v] > dis[u.id] + w)) {dis[v] = dis[u.id] + w;h.push({v, dis[v]});}}return;
}signed main() {cin.tie(0)->sync_with_stdio(false);cin >> n >> p >> x >> q >> y;for (int i = 1; i <= n; ++i) {cin >> a[i];sum += a[i];}if (sum % n == 0) { cout << 0;return 0;}dijkstra(sum);if (!dis.count(0)) {cout << -1;} else {cout << dis[0];}return 0;
}
T3
0 pts。
dfs 没分。
赛时怎么都想不到是种树(把种树忘了)。
如果用普通的区间选点,只有 60 pts。
那么,就使用树状数组优化,时间 \(O(m \log n)\)。
Code
#include <bits/stdc++.h>
#define int long longusing namespace std;const int kMaxN = 1e6 + 5;
int n, m, tr[kMaxN];
bool vis[kMaxN];struct Node {int l, r, k;
} a[kMaxN];bool cmp(Node x, Node y) {if (x.r == y.r) {if (x.l == y.l) {return x.k > y.k;}return x.l < y.l;}return x.r < y.r;
}void update(int idx, int val) {for (; idx <= n; idx += idx & -idx) {tr[idx] += val;}return;
}int query(int idx) {int ans = 0;for (; idx; idx -= idx & -idx) {ans += tr[idx];}return ans;
}signed main() {cin.tie(0)->sync_with_stdio(false);cin >> n >> m;for (int i = 1; i <= m; ++i) {cin >> a[i].l >> a[i].r >> a[i].k;}sort(a + 1, a + m + 1, cmp);for (int i = 1, l, r, k, sum; i <= m; ++i) {l = a[i].l, r = a[i].r, k = a[i].k, sum = query(r) - query(l - 1);if (sum < k) {for (int j = r; j >= l; --j) {if (!vis[j]) {++sum;update(j, 1);vis[j] = 1;if (sum == k) {break;}}}}}cout << query(n);return 0;
}
T4
18 pts。
暴力枚举 \(b\)。
正解是拆成两部分,首先二分最后的数,然后再进行枚举算出答案。
Code
#include <bits/stdc++.h>
#define int __int128using namespace std;
using LL = long long;LL N, M;
int n, m;int C(int x, int k) {return x % 10 + x / 10 % 10 * k + x / 100 * k * k;
}int check(int x, int k) {int ans = 0, t = 1;while (x) {if (x % k > 9) {return -1;}ans += x % k * t;t *= 10;x /= k;}return ans;
}signed main() {cin.tie(0)->sync_with_stdio(false);cin >> N >> M;n = N, m = M;int mx = 10;for (int i = m; i <= 999; ++i) {int lt = 0, rt = 1e18 + 1;for (int mid; lt + 1 < rt;) {mid = lt + rt >> 1;if (C(i, mid) >= n) {rt = mid;} else {lt = mid;}}if (C(i, rt) == n) {mx = max(mx, rt);}}for (int i = 1e6; i >= mx; --i) {if (check(n, i) >= m) {LL I = i;cout << I;return 0;}}LL Mx = mx;cout << Mx;return 0;
}