Codeforces Round #598 (Div. 3)

Codeforces Round #598 (Div. 3)

Posted by hongzhiyin on November 5, 2019

Codeforces Round #598 (Div. 3)

A. Payment Without Change

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ll a, b, n, s;
 
// ------- 函数 ------- //
 
void Init() {
    scanf("%lld%lld%lld%lld", &a, &b, &n, &s);
}
 
int Solve() {
    ll t = s / n;
    a = min(a, t);
    if (s - a * n > b) return puts("NO");
    return puts("YES");
}

B. Minimize the Permutation

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const int N = (int)1e2+7;
 
// ------- 变量 ------- //
 
int n, a[N], vis[N];
 
// ------- 函数 ------- //
 
void Init() {
    memset(vis, 0, sizeof(vis));
    scanf("%d", &n);
    rep(i, 1, n+1) scanf("%d", a+i);
}
 
int Solve() {
    int cnt = 0;
    rep(i, 1, n+1) {
        if (cnt == n - 1) break;
        int pos = find(a + 1, a + n + 1, i) - a - 1;
        while (pos && !vis[pos] && a[pos+1] < a[pos]) {
            swap(a[pos], a[pos+1]);
            vis[pos] = 1;
            pos--;
        }
    }
    rep(i, 1, n+1) printf("%d%c", a[i], " \n"[i==n]);
    return 0;
}

C. Platforms Jumping

贪心

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const int N = (int)3e3+7;
 
// ------- 变量 ------- //
 
int n, m, d;
int c[N], vis[N];
 
// ------- 函数 ------- //
 
void Init() {
    scanf("%d%d%d", &n, &m, &d);
    memset(vis, 0, sizeof(vis));
    rep(i, 1, m+1) scanf("%d", c+i);
}
 
int Solve() {
    int pos = n;
    per(i, 1, m+1) rep(j, 0, c[i]) vis[pos--] = i;
    int cur = 0, id = 0;
    while (1) {
        cur += d;
        if (cur > n) break;
        if (!vis[cur]) {
            ++id;
            if (id > m) return puts("NO");
            rep(i, 0, c[id]) {
                vis[++pos] = 0;
                vis[cur+i] = id;
            }
            cur += c[id] - 1;
        }
    }
    puts("YES");
    rep(i, 1, n+1) printf("%d%c", vis[i], " \n"[i==n]);
    return 0;
}

D. Binary String Minimizing

贪心

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const int N = (int)1e6+7;
 
// ------- 变量 ------- //
 
int n;
ll k;
char s[N];
 
// ------- 函数 ------- //
 
void Init() {
    scanf("%d%lld", &n, &k);
    scanf("%s", s + 1);
}
 
int Solve() {
    ll cnt = 0, pos0 = 1;
    rep(i, 1, n+1) {
        if (cnt == k) break;
        pos0 = max((ll)i, pos0);
        while (pos0 <= n && s[pos0] == '1') pos0++;
        if (pos0 == n + 1) return puts(s + 1);
        if (pos0 - i + cnt >= k) {
            ll pos = pos0;
            while (pos > i) {
                pos--;
                swap(s[pos], s[pos+1]);
                cnt++;
                if (cnt == k) return puts(s + 1);
            }    
        } else {
            cnt += pos0 - i;
            swap(s[i], s[pos0]);
        }
    }
    return puts(s + 1);
}

E. Yet Another Division Into Teams

dp

题意

$n$ 个数,分若干组,每组至少 $3$ 个数。

每组代价为最大值减最小值。

总代价为各组代价之和。

求最小总代价。

$3 \le n \le 2 \cdot 10^5$

$1 \le a_i \le 10^9$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const int N = 2e5+7;
 
// ------- 变量 ------- //
 
int n;
ll dp[N], pre[N];
struct node { int val, id, grp; } a[N];
 
// ------- 函数 ------- //
 
void Init() {
    scanf("%d", &n);
    rep(i, 1, n+1) { scanf("%d", &a[i].val); a[i].id = i; }
}
 
int Solve() {
    sort(a + 1, a + n + 1, [](node &a, node &b){ return a.val < b.val; });
 
    dp[0] = 0; dp[1] = dp[2] = LINF;
    rep(i, 3, n+1) {
        ll t1 = dp[i-3] + a[i].val - a[i-2].val;
        ll t2 = dp[i-1] + a[i].val - a[i-1].val;
        if (t1 < t2) {
            dp[i] = t1;
            pre[i] = 1;
        } else {
            dp[i] = t2;
            pre[i] = 0;
        }
    }
    ll ans1 = dp[n];
    a[n].grp = 0;
    int poi = n;
    while (poi) {
        if (pre[poi]) {
            a[poi-1].grp = a[poi-2].grp = a[poi].grp;
            poi -= 3;
            a[poi].grp = a[poi+1].grp - 1;
        } else {
            a[poi-1].grp = a[poi].grp;
            poi--;
        }
    }
    per(i, 1, n+1) a[i].grp -= a[1].grp - 1;
    int ans2 = a[n].grp;
 
    sort(a + 1, a + n + 1, [](node &a, node &b){ return a.id < b.id; });
 
    printf("%lld %d\n", ans1, ans2);
    rep(i, 1, n+1) printf("%d%c", a[i].grp, " \n"[i==n]);
 
    return 0;
}

F. Equalizing Two Strings

题意

两个字符串 $s$ 和 $t$ ,

每次操作可以选择一个任意长度 $len$ ,

分别翻转 $s$ 和 $t$ 中一个长度为 $len$ 的子串,子串位置可以不同,

问最终是否能使 $s$ 和 $t$ 相同。

题解

  1. 字符种类和个数相同。
  2. 若某种字符超过一个,则可使其中一个字符串不动,必为 $YES$ 。
  3. 否则,即为两个排列,考虑逆序对奇偶性。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const int N = 2e5+7;
 
// ------- 变量 ------- //
 
int n;
char s[N], t[N];
 
// ------- 函数 ------- //
 
char b[N];
void msort(char a[], int l, int r, int &ans) {
    if (l >= r) return;
    int m = (r + l) >> 1;
    msort(a, l, m, ans);
    msort(a, m+1, r, ans);
    int i = l, j = m+1;
    rep(k, l, r+1) {
        if (j > r || i <= m && a[i] <= a[j]) b[k] = a[i++];
        else b[k] = a[j++], ans += m - i + 1;  // ans 为逆序对数
    }
    rep(k, l, r+1) a[k] = b[k];
}
 
void Init() {
    scanf("%d", &n);
    scanf("%s%s", s, t);
}
 
int Solve() {
    int cnt1 = 0, cnt2 = 0;
    msort(s, 0, n-1, cnt1);
    msort(t, 0, n-1, cnt2);
 
    rep(i, 0, n) if (s[i] != t[i]) return puts("NO");
    rep(i, 1, n) if (s[i] == s[i-1]) return puts("YES");
    if (abs(cnt1 - cnt2) & 1) return puts("NO");
    return puts("YES");
}