比赛链接:传送门
A. Payment Without Change
代码:
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int main() {
int T;
cin >> T;
while (T--) {
ll a, b, n, S;
read(a, b, n, S);
ll cnta = min(a, S/n);
ll res = S - cnta * n;
if (res <= b) {
puts("YES");
}
else {
puts("NO");
}
}
return 0;
}
B. Minimize the Permutation
暴力。从1到n枚举,每个数尽量地往前和比他大的数交换。并且保证相邻的位置只能换一次。
交换的时候不考虑两者的大小就会有各种奇奇怪怪的bug。
代码:O($n^{2}$)
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 105
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int a[N];
int main() {
int T;
cin >> T;
while (T--) {
int n; read(n);
for (int i = 1; i <= n; i++) {
read(a[i]);
}
int st = 1;
for (int i = 1; i <= n; i++) {
for (int j = st; j <= n; j++) {
if (a[j] == i) {
for (int k = j-1; k >= st; k--) {
if (a[k] > a[k+1])
swap(a[k], a[k+1]);
else {
break;
}
}
st = max(j, i+1);
}
}
}
for (int i = 1; i <= n; i++) {
printf("%d%c", a[i], " \n"[i==n]);
}
}
return 0;
}
/*
4
4
1 2 4 3
5
5 4 1 3 2
1
1
4
4 3 2 1
*/
C. Platforms Jumping(贪心)
从前到后,贪心地在两岸和木板之间、木板和木板之间插入长度为d-1的“水”,直到“水”的总长度+木板的总长度 = n。
如果“水”的数量超过m+1就是非法的。
否则就得到了一个方案。
代码:O(n)
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 1005
#define M 1005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int c[M];
int ans[N];
vector <int> gaps;
int main() {
int n, m, d;
read(n, m, d);
int sum = 0;
for (int i = 1; i <= m; i++) {
read(c[i]);
sum += c[i];
}
int r = sum;
while (r < n) {
if (r + d-1 <= n) {
gaps.push_back(d-1);
r += d-1;
}
else {
gaps.push_back(n - r);
r = n;
}
if (sz(gaps) > m+1)
break;
}
if (sz(gaps) > m+1) {
return puts("NO"), 0;
}
else {
puts("YES");
int idgap = 0, idc = 1;
for (int i = 1; i <= n;) {
if (idgap < sz(gaps)) {
for (int j = 0; j < gaps[idgap]; j++) {
ans[i++] = 0;
}
idgap++;
}
for (int j = 0; j < c[idc]; j++) {
ans[i++] = idc;
}
idc++;
}
for (int i = 1; i <= n; i++) {
printf("%d%c", ans[i], " \n"[i==n]);
}
}
return 0;
}
D. Binary String Minimizing(贪心+双指针)
从左到右每个0依次和当前最左边的1交换,消耗这两个数下标之差的交换次数。
如果次数不够用,就让这个0和最远的能交换的1交换位置。
代码:O(n)
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int main() {
int q; cin >> q;
while (q--) {
ll n, k; read(n, k);
string s; cin >> s;
int st1 = 0;
ll resk = k;
while (st1 < n && s[st1] == '0')
st1++;
for (int i = st1; i < n; i++) {
if (s[i] == '0') {
if (i - st1 <= resk) {
resk -= i - st1;
swap(s[i], s[st1]);
st1++;
}
else {
swap(s[i], s[i - resk]);
resk = 0;
break;
}
}
}
cout << s << endl;
}
return 0;
}
E. Yet Another Division Into Teams(dp+转移路径)
让能力相近的选手组队是最好的。
组成人数x >= 6人的队伍不如把能力最大的3人提出来组成1个3人队+1个x-3人队,所以只用考虑3、4、5人的队伍。
对数组a排序后,设$f_{i}$表示前i个人组完队后得到的最小的total diversity。
对每个i考虑$f_{i}从f_{i-3}、f_{i-4}、f_{i-5}$转移,因为数组a已经排过序了,i-j产生的diversity就是a[i] - a[i-j+1]。
记录转移时的前驱。最后相同区间内的人都分到同一组。
代码:O(n)
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
struct Node{
ll val;
int id;
bool operator < (const Node& x) const {
return val < x.val;
}
}a[N];
ll sum[N];
ll f[N];
int pre[N];
int ans[N];
int main() {
int n; read(n);
sum[0] = 0;
for (int i = 1; i <= n; i++)
read(a[i].val),
a[i].id = i,
sum[i] = sum[i-1] + a[i].val;
sort(a+1, a+1+n);
memset(f, 0x3f, sizeof f);
f[0] = 0;
pre[0] = -1;
for (int i = 3; i <= n; i++) {
for (int j = 3; j <= 5; j++) {
if (i-j >= 0 && f[i] > f[i-j] + a[i].val - a[i-j+1].val) {
f[i] = f[i-j] + a[i].val - a[i-j+1].val;
pre[i] = i-j;
}
}
}
int tot = 0;
for (int i = n; i >= 1; i = pre[i]) {
++tot;
for (int j = i; j > pre[i]; j--) {
ans[a[j].id] = tot;
}
}
cout << f[n] << ' ' << tot << endl;
for (int i = 1; i <= n; i++) {
printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}
F. Equalizing Two Strings(逆序对)
因为交换次数任意,所以len > 2的操作都可以看作若干次len = 2的操作的叠加。不妨只考虑len = 2的操作。
①:如果字母构成不同一定不行。
②:如果字母构成相同,并且至少有一个字母重复出现,一定可行。可以先把s中两个相同的字母换到最左边,然后s中选择区间[1,2]时,t串中任意相邻的两个字母可以无限交换。
③:如果字母构成相同,并且没有重复字母。在s中选择一个len = 2的区间,再在t中选择一个len = 2的区间,就相当于在t中选择两个len = 2的区间。
那么只要t能在偶数次len = 2的操作中得到s,就可行,否则就不可行。(此时t长度最多26,冒泡排序就行)
代码:O(n + $26^{2}$)
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int n;
string s, t;
int cnts[30], cntt[30];
bool solve() {
for (int i = 0; i < 26; i++) {
if (cnts[i] != cntt[i])
return false;
}
for (int i = 0; i < 26; i++) {
if (cnts[i] > 1)
return true;
}
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (t[j] == s[i]) {
for (int k = j-1; k >= i; k--) {
swap(t[k+1], t[k]);
cnt++;
}
}
}
}
return cnt % 2 == 0;
}
int main() {
int q; cin >> q;
while (q--) {
cin >> n;
cin >> s >> t;
memset(cnts, 0, sizeof cnts);
memset(cntt, 0, sizeof cntt);
for (int i = 0; i < n; i++) {
cnts[s[i]-'a']++;
cntt[t[i]-'a']++;
}
bool ans = solve();
if (ans)
puts("YES");
else
puts("NO");
}
return 0;
}