A. Diagonal Walking
模拟
点击查看代码
void solve() {int n;std::cin >> n;std::string s;std::cin >> s;int ans = n;for (int i = 0; i + 1 < n; ++ i) {if ((s[i] == 'R' && s[i + 1] == 'U') || (s[i] == 'U' && s[i + 1] == 'R')) {-- ans;++ i;}}std::cout << ans << "\n";
}
B. String Typing
题意:你要构造一个字符串,每次可以添加一个字符,你有一次操作机会可以把当前字符串复制一份到后面。求构造出给定字符串的最小次数。
找最长的前缀使得后面和它相邻的长度相等的串和它一样。
点击查看代码
void solve() {int n;std::cin >> n;std::string s;std::cin >> s;int ans = n;for (int i = 0; i < n / 2; ++ i) {if (s.substr(0, i + 1) == s.substr(i + 1, i + 1)) {ans = std::min(ans, i + 1 + 1 + n - (i + 1) * 2);}}std::cout << ans << "\n";
}
C. Matrix Walk
题意:一个矩阵\((i, j)\)位置上的数是\(y(i-1) + j\)。现在给出一个移动序列上每次到达位置上的数,只能上下左右移动。求\(x, y\)。
左右移动只会使得值减少一,上下移动则会减少\(y\)。那么我们记录相邻两个数的差,看除了1之外出现的数是不是只有一个。然后如果只有一个,就以这个数作为\(y\)。然后检查距离为1的数是不是在同一行。
\(x\)取个最大值就行。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}std::set<int> s;for (int i = 0; i + 1 < n; ++ i) {if (std::abs(a[i + 1] - a[i]) != 1) {s.insert(std::abs(a[i + 1] - a[i]));}}if (s.size() > 1) {std::cout << "NO\n";} else {int x = 1e9;if (s.empty()) {std::cout << "YES\n";std::cout << x << " " << 1 << "\n";return;}int y = *s.begin();if (y == 0) {std::cout << "NO\n";return;}for (int i = 0; i + 1 < n; ++ i) {if (std::abs(a[i + 1] - a[i]) == 1 && (a[i] - 1) / y != (a[i + 1] - 1) / y) {std::cout << "NO\n";return;}}std::cout << "YES\n";std::cout << x << " " << y << "\n";}
}
D. Fight Against Traffic
题意:给你一个图,有多少点使得向他们连边不会影响\(s\)到\(t\)的最短路?
\(s\)和\(t\)分别做一次\(dijkstra\)。
然后枚举点对,如果起点分别到两个点然后到终点的距离大于等于最短路,就合法。
点击查看代码
void solve() {int n, m, s, t;std::cin >> n >> m >> s >> t;-- s, -- t;std::vector<std::vector<int>> adj(n);for (int i = 0; i < m; ++ i) {int u, v;std::cin >> u >> v;-- u, -- v;adj[u].push_back(v);adj[v].push_back(u);}auto dijkstra = [&](std::vector<int> & dist, int s) -> void {using PII = std::pair<int, int>;std::priority_queue<PII, std::vector<PII>, std::greater<PII>> heap;dist[s] = 0;heap.emplace(dist[s], s);while (heap.size()) {auto [d, u] = heap.top(); heap.pop();if (d != dist[u]) {continue;}for (auto & v : adj[u]) {if (dist[v] > d + 1) {dist[v] = d + 1;heap.emplace(dist[v], v);}}}};const int inf = 1e9;std::vector<int> dists(n, inf), distt(n, inf);dijkstra(dists, s);dijkstra(distt, t);int ans = 0, d = dists[t];for (int i = 0; i < n; ++ i) {for (int j = i + 1; j < n; ++ j) {if (dists[i] + 1 + distt[j] >= d && dists[j] + 1 + distt[i] >= d) {++ ans;}}}std::cout << ans - m << "\n";
}
E. Water Taps
题意:\(x_i \in [0, a_i]\),要使得\(\sum_{i=1}^{n} x_i \times (t_i - T) = 0\),并且要求\(\sum_{i=1}^{n} x_i\)最大。\(x_i\)可以是实数。
直接贪心都选了,然后如果总和小于0,就把\(t_i -T\)为负数的从小到大去掉,如果大于0,则把\(t_i - T\)为正数的从大到小去掉。因为去掉的数可以是实数,所以这样一定更优。
点击查看代码
void solve() {int n;double T;std::cin >> n >> T;std::vector<std::pair<double, double>> a(n);double ans = 0, sum1 = 0, sum2 = 0;for (int i = 0; i < n; ++ i) {std::cin >> a[i].second;}std::vector<std::pair<double, double>> b, c;for (int i = 0; i < n; ++ i) {std::cin >> a[i].first;a[i].first -= T;if (a[i].first == 0) {ans += a[i].second;} else if (a[i].first < 0) {b.emplace_back(a[i]);sum1 += a[i].first * a[i].second;} else {c.emplace_back(a[i]);sum2 += a[i].first * a[i].second;}}std::ranges::sort(b, std::greater<>());std::ranges::sort(c);if (sum1 == 0 || sum2 == 0) {} else if (sum1 == sum2) {for (auto & [y, x] : b) {ans += x;}for (auto & [y, x] : c) {ans += x;}} else if (-sum1 < sum2) {double sum = sum1;for (auto & [y, x] : b) {ans += x;}for (auto & [y, x] : c) {if (sum + x * y >= 0) {ans += -sum / y;break;} else {ans += x;sum += x * y;}}} else {double sum = sum2;for (auto & [y, x] : c) {ans += x;}for (auto & [y, x] : b) {if (sum + x * y <= 0) {ans += -sum / y;break;} else {ans += x;sum += x * y;}}}std::cout << std::fixed << std::setprecision(12);std::cout << ans << "\n";
}