The 2024 ICPC Kunming Invitational Contest
A - Two-star Contest
题意
思路
答奋题,贴队友的代码
代码
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define endl '\n';
#define inf 1e18
using namespace std;
struct node {
int i;
int s = 0;
int sum = 0, cnt = 0;
queue<int> q;
friend bool operator > (node n1, node n2) {
return n1.s > n2.s;
}
};
void solve() {
int n, m, k;
cin >> n >> m >> k;
vector<vector<int> > t(n + 1, vector<int>(m + 1));
vector<node> ord(n + 1);
vector<int> c(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> ord[i].s;
ord[i].i = i;
c[i] = ord[i].s;
for (int j = 1; j <= m; ++j) {
cin >> t[i][j];
if (t[i][j] == -1) ord[i].cnt++;
else ord[i].sum += t[i][j];
}
}
sort(c.begin(), c.end());
for (int i = 1; i <= n; ++i) {
ord[i].s = lower_bound(c.begin(), c.end(), ord[i].s) - c.begin();
}
vector<node> d[n + 1];
for (int i = 1; i <= n; ++i) {
d[ord[i].s].push_back(ord[i]);
}
int lim = inf;
for (int i = n; i; --i) {
int res = inf;
if (!d[i].size()) continue;
for (auto nn : d[i]) {
if (nn.sum >= lim) {
cout << "No" << endl;
return;
}
for (int j = 1; j <= nn.cnt; ++j) {
if (nn.sum + k < lim) {
nn.sum += k;
ord[nn.i].q.push(k);
}
else {
ord[nn.i].q.push(lim - nn.sum - 1);
nn.sum += lim - nn.sum - 1;
}
}
res = min(res, nn.sum);
}
lim = res;
}
cout << "Yes" << endl;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (t[i][j] != -1) cout << t[i][j] << ' ';
else {
cout << ord[i].q.front() << ' ';
ord[i].q.pop();
}
}
cout << endl;
}
};
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
B - Gold Medal
题意
思路
把\(a_i\)补成\(k\)的倍数,每次取补的最少的加到答案(要补的一样,先取大的和先取小的无所谓),同时减少\(m\),不够补就直接加。最后如果\(m\)有剩还要加\(\lfloor {\frac m k} \rfloor\)
代码
点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;
const int mxn = 2e5 + 10;
void solve()
{
int n, k, m;
cin >> n >> k;
vector<pii> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i].second;
a[i].first = k - a[i].second % k;
}
cin >> m;
sort(a.begin(), a.end());
int ans = 0;
for (int i = 0; i < n; i++)
{
if (m - a[i].first >= 0)
{
ans += (a[i].first + a[i].second) / k;
m -= a[i].first;
}
else
{
ans += (a[i].second + m) / k;
m = 0;
}
}
ans += m / k;
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int __ = 1;
cin >> __;
while (__--)
{
solve();
}
return 0;
}
E - Relearn through Review
题意
思路
维护原数组的前缀\(gcd\)和后缀\(gcd\),枚举区间并加上\(k\),当前\(gcd\)就是前缀\(gcd\)、后缀\(gcd\)和当前区间\(gcd\)的\(gcd\)。此时还是\(O(n^2)\),由于前缀\(gcd\)不会增大,只有在减小的时候会改变当前\(gcd\),所以\(gcd\)相同的部分可以跳过
代码
点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;
const int mxn = 2e5 + 10;
void solve()
{
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
vector<int> pre(n), suf(n);
pre[0] = a[0];
for (int i = 1; i < n; i++)
{
pre[i] = gcd(pre[i - 1], a[i]);
}
suf[n - 1] = a[n - 1];
for (int i = n - 2; i >= 0; i--)
{
suf[i] = gcd(suf[i + 1], a[i]);
}
int ans = pre[n - 1];
for (int i = 0; i < n; i++)
{
if (i && pre[i] == pre[i - 1])
{
continue;
}
int t = pre[max(0LL, i - 1)];
for (int j = i; j < n; j++)
{
if (j == 0)
{
t = a[j] + k;
}
else
{
t = gcd(t, a[j] + k);
}
if (j != n - 1)
{
ans = max(ans, gcd(t, suf[j + 1]));
}
}
ans = max(ans, t);
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int __ = 1;
cin >> __;
while (__--)
{
solve();
}
return 0;
}
G - Be Positive
题意
思路一
\(n =1\) 和 \(n\ mod\ 4=0\) 都不行,因为所有数异或起来就是0。其他按\(4\)个一组,交换相邻两组元素即是最小字典序
代码一
点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;
const int mxn = 2e5 + 10;
void solve()
{
int n;
cin >> n;
if (n == 1 || n % 4 == 0)
{
cout << "impossible" << endl;
return;
}
vector<int> a(n);
iota(a.begin(), a.end(), 0);
swap(a[0], a[1]);
for (int i = 3; i < n; i += 4)
{
swap(a[i], a[i + 1]);
}
for (auto& i : a)
{
cout << i << " ";
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int __ = 1;
cin >> __;
while (__--)
{
solve();
}
return 0;
}
思路二
代码二
点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
const int mxn = 1e6 + 10;
bool sta[mxn];
void init()
{
vector<int> sum(31);
for (int i = 0; i < mxn; i++)
{
int x = i, cnt = 1;
while (x)
{
sum[cnt] += x & 1;
cnt++;
x >>= 1;
}
for (int j = 0; j < 31; j++)
{
if (sum[j] & 1)
{
sta[i] = true;
break;
}
}
}
}
void solve()
{
int n;
cin >> n;
if (!sta[n - 1])
{
cout << "impossible" << endl;
return;
}
for (int i = 0; i < n; i++)
{
if (!sta[i])
{
cout << i + 1;
}
else if (i && !sta[i - 1])
{
cout << i - 1;
}
else
{
cout << i;
}
cout << " ";
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
init();
int __ = 1;
cin >> __;
while (__--)
{
solve();
}
return 0;
}
I - Left Shifting 2
题意
思路
可以看出一个字符相同的子串的贡献是\(\lfloor {\frac n 2} \rfloor\)(\(n\)为子串长度);而对于左移操作,只有将偶数长度的子串的一个字符移到开头,其他在结尾才能减少\(1\)的操作数。因此要考虑是否有偶数长度的子串以及这个子串是否能被“隔开”,只有两个条件都满足才能减少\(1\)的操作数
代码
点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;
const int mxn = 2e5 + 10;
void solve()
{
string s;
cin >> s;
int ans = 0;
unordered_set<char> st;
bool even = false, div = false;
for (auto& i : s)
{
st.insert(i);
}
int cnt = 0;
if ((int)st.size() > 1)
{
div = true;
// 排除首尾相同且是偶数长度的情况
while (s.back() == s[cnt])
{
s.push_back(s[cnt]);
cnt++;
}
}
s.push_back('%');
for (int i = cnt; i < (int)s.size();)
{
int p = i;
while (s[++p] == s[i]);
ans += (p - i) >> 1;
if ((p - i) % 2 == 0)
{
even = true;
}
i = p;
}
cout << ans - (even && div) << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int __ = 1;
cin >> __;
while (__--)
{
solve();
}
return 0;
}






浙公网安备 33010602011771号