> 文章列表 > The 2022 ICPC Asia Xian Regional Contest

The 2022 ICPC Asia Xian Regional Contest

The 2022 ICPC Asia Xian Regional Contest

题目顺序大致按照难度排序。

F. Hotel

现在酒店中有单人间和双人间,价格分别是c1,c2,现在有n个队,每队三个人,性别分别用字母表示,当两个人性别相同且在同一个队时,他们可以住在双人间中。求最少需要多少钱使得n个队住下。

思路:直接模拟。

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e5 + 5;
ll n, c1, c2;
std::string s;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> n >> c1 >> c2;ll ans = 0;for(int i = 1; i <= n; i ++) {std::cin >> s;std::sort(s.begin(), s.end());if(s[0] == s[1] || s[1] == s[2]) {ans += std::min(c1, c2) + std::min(c1 * 2, c2);  }elseans += std::min(c1, c2) * 3;}std::cout << ans << '\\n';return 0;
}

 J. Strange Sum

给出n个数的序列a,可以从中选择一些数字,但是如果选择了a[i],则要满足序列中所有长度为i的子串中最多有两个数被选到,现在求选择的数和最大是多少,注意,可以不选任何数。

思路:假设我们选择了三个数a[i]、a[j]和a[k],且k>j>i,那么在1~k区间内就会有三个数,不满足条件,可以得到最多选择两个数。排序贪心选择即可。

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e5 + 5;
int n;
int a[N];int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> n;for(int i = 1; i <= n; i ++) {std::cin >> a[i];}std::sort(a + 1, a + 1 + n, std::greater<int>());std::cout << std::max({0, a[1], a[1] + a[2]}) << '\\n';return 0;
}

C. Clone Ranran

有个人要准备c道题,他可以进行如下两种操作:花费a分钟克隆一个自己;花费b分钟准备一道题目。问准备c道题最少需要多长时间。

思路:最优选择一定是先尽可能快的克隆自己,然后最后一起花b分钟准备一道题,得到的计算式是a\\times x + \\left \\lceil \\frac{c}{2^{x}} \\right \\rceil \\times b,x是克隆的次数。

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e5 + 5;
int t;
ll a, b, c;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {std::cin >> a >> b >> c;ll ans = 1e18;for(int i = 0; i <= 30; i ++) {ll res = 1 << i;res = (ll)(ceil(c * 1.0 / res));ans = std::min(ans, a * i + res * b);}std::cout << ans << '\\n';}return 0;
}

 G. Perfect Word

给出n个字符串,对于一个字符串,若它的所有子串都出现在了这n个字符串中,则称这个字符串是good的,则最大的good串的长度是多少。

思路:可以从数据范围考虑起。若一个字符串能成为good字符串,且长度为x,那么它的x * (x + 1) / 2个子串都要出现,这样想good串长度最多是根下1e5级别,我们大约可以用350代替。然后考虑暴力,如果所有的串长度都是350,那一共最多有1e5 / 350个字符串,完全可以暴力,这样循环的时间复杂度是1e7级别,可以过。

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e5 + 5;
int n;
std::string s[N];
std::unordered_map<std::string, int> mp;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> n;for(int i = 1; i <= n; i ++) {std::cin >> s[i];mp[s[i]] ++;}int ans = 0;for(int i = 1; i <= n; i ++) {int len = s[i].length();bool flag = true;for(int j = 0; j < len; j ++) {for(int k = 1; k <= len; k ++) {if(j + k - 1 >= len) continue;std::string ss = s[i].substr(j, k);if(!mp[ss]) {flag = false;break;}}if(!flag) break;}if(flag)ans = std::max(ans, (int)s[i].length());}std::cout << ans << '\\n';return 0;
}

E. Find Maximum

 给出函数f(x),回答t次询问,每次给出l和r,求区间[l, r]之间最大的f(x)是多少。

思路:f(x)的值可以联想到三进制,不过它是x的三进制加位数的和,那就直接贪心,使得三进制下每一位2的数量尽可能多。

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e5 + 5;
int t;
ll f[N];std::vector<int> get3(ll x) {std::vector<int> vec;while(x) {int num = x % 3;vec.push_back(num);x /= 3;}reverse(vec.begin(), vec.end());return vec;
}ll getans(ll x) {if(!x) return 1;else if(x % 3 == 0) return getans(x / 3) + 1;else return getans(x - 1) + 1;
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {ll l, r;std::cin >> l >> r;std::vector<int> R = get3(r);ll ans = std::max(getans(l), getans(r));int n = R.size();for(int i = 0; i < n; i ++) {ll res = 0;if(R[i] == 0) continue;for(int j = 0; j < i; j ++) {res = res * 3 + R[j];}res = res * 3 + R[i] - 1;for(int j = i + 1; j < n; j ++) {res = res * 3 + 2;}if(res >= l)ans = std::max(ans, getans(res));}std::cout << ans << '\\n';}return 0;
}

 L. Tree

定义节点u的subtree(u)是以u为根的子树中所有节点的集合,现在称集合S是good的当且仅当它满足至少一个条件:1、对于S中所有不同的u和v,满足u是vsubtree中的一点或反之;2、对于S中所有不同的u和v,他们两个没有父子树关系。现给出一棵树,问可以划分的good集合数最小是多少。

思路:官方题解:

 解释一下概念:链和反链是在简单有向无环图中定义的,在一条路径中出现的点,是在一条链上;不在一条路径上出现的点,即无法相互到达的点,是在一条反链上,形象的来说,在题目给定的树中,可以定义这棵树是以根节点为起始点的有向图,那么链就是在一条路径中的点,反链连接的就是若干叶子结点(也不一定都是叶子结点)。 

AC Code:

#include <bits/stdc++.h>typedef long long ll;
const int N = 1e6 + 5;
int t, n;
int d[N], cnt[N], dep[N];
std::vector<int> vec[N];int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {std::cin >> n;for(int i = 1; i <= n; i ++) {vec[i].clear();d[i] = cnt[i] = dep[i] = 0;}for(int i = 2; i <= n; i ++) {int u;std::cin >> u;d[u] ++;vec[i].push_back(u);}std::queue<int> q;for(int i = 1; i <= n; i ++) {if(!d[i]) {q.push(i);dep[i] = 1;}}while(!q.empty()) {int now = q.front();q.pop();for(auto u : vec[now]) {dep[u] = dep[now] + 1;d[u] --;if(!d[u]) {q.push(u);}}}for(int i = 1; i <= n; i ++) {cnt[dep[i]] ++;}int ans = 2e9;for(int i = 1; i <= n; i ++) {ans = std::min(ans, cnt[i] + i - 1);}std::cout << ans << '\\n';}    return 0;
}

 气,感觉铜牌题看了题解也不难,但是赛时想不到www

B是网络流?没学,爬了