比赛链接:传送门

 

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;
}
View Code

 

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
*/
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

 

01-10 10:44