https://codeforces.com/contest/1256/p
A. Payment Without Change
题意 给了 a 个 n价值硬币 b个 1价值硬币 能不能拼出 S 问
直接算下就行
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
#define int long long
long long cas, a, b, n, s;
signed main() {
cin >> cas;
while(cas --) {
cin >> a >> b >> n >> s;
if(a * n >= s) {
int t = s / n;
s -= t * n;
if(s > b) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
}
} else {
s -= n * a;
if(s > b) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
}
}
}
return 0;
}
B. Minimize the Permutation
一开始读错题了 以为是随意交换n - 1次
题意 : 相邻的位置 可以交换 这相邻位置一旦交换过就不在执行
考虑 贪心的选择 第i大小数据放置到对应位置 同时我标记了这个是否换过 贪心到底就可以了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
#define int long long
long long cas, b, n, s;
int a[maxn];
map<pair<int, int>, int> vis;
signed main() {
cin >> cas;
while(cas --) {
vis.clear();
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
int cnt = n - 1;
for(int i = 1; i <= n; i ++) {
int pos = 0;
for(int j = 1; j <= n; j ++) {
if(a[j] == i)
pos = j;
}
while(pos > i && a[pos] < a[pos - 1] && cnt > 0 && !vis[make_pair(pos, pos - 1)]) {
swap(a[pos - 1], a[pos]);
vis[make_pair(pos, pos - 1)] = 1;
pos --;
cnt --;
}
}
for(int i = 1; i <= n; i ++)
cout << a[i] << " ";
cout << endl;
}
return 0;
}
C. Platforms Jumping
题意 给了你一些跳板 让你找到一个排列使你每次最多在跳d格的情况下 跳到n + 1 位置 (不是 n 位置 我wa14醉了)
一开始我们考虑 所有板子按顺序连续 挨着最右端排布 只要人跳不到 就接个板过去 看看最后我们能不能到n + 1 位置 同时 如果这人 可以直接调到后面连续的板子上 那么 我们就直接当他能去就好了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
#define int long long
int cas;
int n, m, k, d;
string str, ans;
int a[maxn], h[maxn];
signed main() {
cin >> n >> m >> d;
int p1 = n;
for(int i = 1; i <= m; i ++) cin >> h[i], p1 -= h[i];
p1 += 1;
int pos = 0;
int cnt = 1;
while(pos < n) {
// cout << pos << " " << p1 << " " << cnt << endl;
if(pos + d < p1) {
pos += d;
for(int i = 1; i <= h[cnt]; i ++) {
a[pos + i - 1] = cnt;
}
if(cnt == m + 1) break;
pos += h[cnt] - 1;
p1 += h[cnt];
cnt ++;
} else {
pos = n + 1;
}
}
if(pos <= n) cout << "NO" << endl;
else {
cout << "YES" << endl;
int j = n;
for(int i = m; i >= cnt; i --) {
for(int t = 1; t <= h[i]; t ++) {
a[j] = i;
j --;
}
}
for(int i = 1; i <= n; i ++) {
cout << a[i] << " ";
}cout << endl;
}
return 0;
}
D. Binary String Minimizing
仍然是 使 字典序最小 同时 01串 如果想让它尽可能的小 显然我尽可能的提0
其实 我们肯定是将0提到前面 假定-1位置是个0 那么 每次遇到一个0 我们都是尽可能把它放到前一个0的位置后面一个 这样在操作数不够的时候我们只需要尽可能提0到最前位置 操作数够的 放到前一个0位置之后就好 O(1)的交换
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
#define int long long
int cas;
int n, k;
string str, ans;
signed main() {
cin >> cas;
while(cas --) {
cin >> n >> k;
cin >> str;
ans = str;
int p1 = 0, p2 = 0;
while(p1 < str.size() && str[p1] == '0') p1 ++;
p2 = p1;
for(int i = p1; i < str.size();) {
while(i < str.size() && str[i] == '1') {
i ++;
}
if(i == n) break;
int t = min(k, i - p1);
// cout << p1 << " " << i << " " << k << " " << t << endl;
ans[i - t] = '0';
str[i] = '1';
ans[i] = '1';
p1 ++;
// cout << ans << endl;
k -= t;
if(k == 0) break;
}
cout << ans << endl;
}
return 0;
}
E. Yet Another Division Into Teams
题意 : 你要进行分队 每队至少3人 你的目的是让每队 内的 最大值 减 最小值 求和 尽可能的小
我们考虑 先排序 让每队尽可能的差小 显然 如果满足6人 我们一定把它拆了
1 2 4 6 7 8 这样的数据一次作差 1 2 2 1 1 我们从中分开 显然会少加一个数据作为最大值减最小值 ans变小
满足6人 显然拆2队比较合适 这样 我们dp复杂度就降低了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 2005;
const int mod = 1e9 + 7;
pair<int, int> a[maxn];
int dp[maxn];
int ans[maxn];
int n, m;
signed main() {
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i].first, a[i].second = i;
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; i ++) {
dp[i] = 0x3f3f3f3f;
for(int j = 3; j <= min(i, 6); j ++) {
if(dp[i] > dp[i - j] + a[i].first - a[i - j + 1].first)
dp[i] = dp[i - j] + a[i].first - a[i - j + 1].first;
}
}
int cnt = 0;
for(int i = n; i; ) {
for(int j = 3; j <= min(6, i); j ++) {
if(dp[i] == dp[i - j] + a[i].first - a[i - j + 1].first) {
++ cnt;
for(int k = 1; k <= j; k ++) ans[a[i - k + 1].second] = cnt;
i = i - j;
break;
}
}
}
cout << dp[n] << " " << cnt << endl;
for(int i = 1; i <= n; i ++)
cout << ans[i] << " ";
cout << endl;
return 0;
}
F. Equalizing Two Strings
题意 你可以无限次交换相邻2个数据 但是 上下交换的次数得一直 要求你换的一样
一开始就考虑到逆序对了
然后 考虑 无解的情况只有数据字母对不上 还有 逆序对奇偶性不一样
这样大概就过 其实 如果字母个数对上 一旦某个数据 出现2次 那么 就意味着 可以另外一个串可以在不改动的情况下 自己可以无限交换
abcc 和 cabc 只要c换到一起 我们每次换cc 就可以 在不改变一个串的情况下 无限改另外一个串
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 2005;
string s1, s2;
string S, T;
int cas, n;
int cal(const string& s) {
int ret = 0;
for(int i = 0; i < n; i ++)
for(int j = 0; j < i; j ++)
if(s[i] < s[j])
ret ++;
return ret;
}
signed main() {
cin >> cas;
while(cas --) {
cin >> n;
cin >> s1 >> s2;
S = s1, T = s2;
int f = 0;
sort(s1.begin(), s1.end());
sort(s2.begin(), s2.end());
for(int i = 0; i < n; i ++) {
if(s1[i] != s2[i]) {
f = 1;
cout << "NO" << endl;
break;
}
}
if(f) continue;
for(int i = 1; i < n; i ++) {
if(s1[i] == s1[i - 1] || s2[i] == s2[i - 1]) {
f = 1;
cout << "YES" << endl;
break;
}
}
if(f) continue;
if(cal(S) % 2 == cal(T) % 2)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}