Loading [MathJax]/extensions/tex2jax.js

Codeforces Round #609 (Div. 1) – 解题报告

A – Long Beautiful Integer

取前\(k\)做循环节,并且对之后的每一个长为\(k\)的节进行大小比较,如果第一循环节小了就加个一即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// CF1268A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 2e5 + 200;
int n, k;
char str[MAX_N];
int digits[MAX_N];
int main()
{
scanf("%d%d%s", &n, &k, str + 1);
for (int i = 1; i <= n; i++)
digits[i] = str[i] - '0';
// compare the nxt substr;
bool flag = false;
for (int i = k + 1; i <= n; i++)
if (digits[(i - 1) % k + 1] > digits[i])
break;
else if (digits[(i - 1) % k + 1] < digits[i])
{
flag = true;
break;
}
if (flag)
digits[k]++;
for (int i = k; i >= 1; i--)
if (digits[i] >= 10)
digits[i] -= 10, digits[i - 1]++;
printf("%d\n", n);
for (int i = 1; i <= n; i++)
printf("%d", digits[(i - 1) % k + 1]);
return 0;
}
// CF1268A.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 2e5 + 200; int n, k; char str[MAX_N]; int digits[MAX_N]; int main() { scanf("%d%d%s", &n, &k, str + 1); for (int i = 1; i <= n; i++) digits[i] = str[i] - '0'; // compare the nxt substr; bool flag = false; for (int i = k + 1; i <= n; i++) if (digits[(i - 1) % k + 1] > digits[i]) break; else if (digits[(i - 1) % k + 1] < digits[i]) { flag = true; break; } if (flag) digits[k]++; for (int i = k; i >= 1; i--) if (digits[i] >= 10) digits[i] -= 10, digits[i - 1]++; printf("%d\n", n); for (int i = 1; i <= n; i++) printf("%d", digits[(i - 1) % k + 1]); return 0; }
// CF1268A.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 2e5 + 200;

int n, k;
char str[MAX_N];
int digits[MAX_N];

int main()
{
    scanf("%d%d%s", &n, &k, str + 1);
    for (int i = 1; i <= n; i++)
        digits[i] = str[i] - '0';
    // compare the nxt substr;
    bool flag = false;
    for (int i = k + 1; i <= n; i++)
        if (digits[(i - 1) % k + 1] > digits[i])
            break;
        else if (digits[(i - 1) % k + 1] < digits[i])
        {
            flag = true;
            break;
        }
    if (flag)
        digits[k]++;
    for (int i = k; i >= 1; i--)
        if (digits[i] >= 10)
            digits[i] -= 10, digits[i - 1]++;
    printf("%d\n", n);
    for (int i = 1; i <= n; i++)
        printf("%d", digits[(i - 1) % k + 1]);
    return 0;
}

C – K Integers

这道题还蛮有意思的。我们考虑最后答案应该是先把子段拼出来,然后再内部排序。内部排序的就可以动态维护一下逆序对即可,那么拼成子段就比较麻烦。不妨把\([1, k]\)的数字都设为\(1\),剩下的设置为\(0\)。那么,我们现在就是要把一堆\(1\)拼在一起。我们可以枚举子段的中点,然后把这些\(1\)向该点靠近,然后算出移动代价。可以发现这就有点像货仓选址,二分找下即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// CF1268C.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX_N = 2e5 + 200;
ll n, pi[MAX_N], pos[MAX_N], nodes[2][MAX_N], inv_f[MAX_N], ans[MAX_N];
bool vis[MAX_N];
inline int lowbit(int x) { return x & (-x); }
void update(int id, int x, ll d)
{
for (; x <= n; x += lowbit(x))
nodes[id][x] += d;
}
ll query(int id, int x, ll ret = 0)
{
for (; x > 0; x -= lowbit(x))
ret += nodes[id][x];
return ret;
}
int main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &pi[i]), pos[pi[i]] = i;
for (int i = 1; i <= n; i++)
{
inv_f[i] = inv_f[i - 1] + i - query(0, pos[i]) - 1;
update(0, pos[i], 1);
}
memset(nodes[0], 0, sizeof(nodes[0]));
ll LB = n, RB = 1;
for (int i = 1; i <= n; i++)
update(0, i, 1), update(1, i, i), vis[i] = true;
for (int i = 1; i <= n; i++)
{
LB = min(LB, pos[i]), RB = max(RB, pos[i]);
update(0, pos[i], -1), update(1, pos[i], -pos[i]), vis[pos[i]] = false;
int l = LB, r = RB, res = LB;
while (l <= r)
{
int mid = (l + r) >> 1;
int l_key = query(0, mid - 1) - query(0, LB);
int r_key = query(0, RB) - query(0, mid);
l_key = mid - LB - l_key, r_key = RB - mid - r_key;
if (l_key <= r_key)
res = mid, l = mid + 1;
else
r = mid - 1;
}
ll k1 = query(1, res) - query(1, LB), k1_ = query(0, res) - query(0, LB);
ll k2 = query(1, RB) - query(1, res), k2_ = query(0, RB) - query(0, res);
ans[i] = (k1 - k1_ * LB - (k1_ * (k1_ - 1) / 2)) + (k2_ * RB - k2 - (k2_ * (k2_ - 1) / 2));
}
for (int i = 1; i <= n; i++)
printf("%lld ", inv_f[i] + ans[i]);
return 0;
}
// CF1268C.cpp #include <bits/stdc++.h> #define ll long long using namespace std; const int MAX_N = 2e5 + 200; ll n, pi[MAX_N], pos[MAX_N], nodes[2][MAX_N], inv_f[MAX_N], ans[MAX_N]; bool vis[MAX_N]; inline int lowbit(int x) { return x & (-x); } void update(int id, int x, ll d) { for (; x <= n; x += lowbit(x)) nodes[id][x] += d; } ll query(int id, int x, ll ret = 0) { for (; x > 0; x -= lowbit(x)) ret += nodes[id][x]; return ret; } int main() { scanf("%lld", &n); for (int i = 1; i <= n; i++) scanf("%lld", &pi[i]), pos[pi[i]] = i; for (int i = 1; i <= n; i++) { inv_f[i] = inv_f[i - 1] + i - query(0, pos[i]) - 1; update(0, pos[i], 1); } memset(nodes[0], 0, sizeof(nodes[0])); ll LB = n, RB = 1; for (int i = 1; i <= n; i++) update(0, i, 1), update(1, i, i), vis[i] = true; for (int i = 1; i <= n; i++) { LB = min(LB, pos[i]), RB = max(RB, pos[i]); update(0, pos[i], -1), update(1, pos[i], -pos[i]), vis[pos[i]] = false; int l = LB, r = RB, res = LB; while (l <= r) { int mid = (l + r) >> 1; int l_key = query(0, mid - 1) - query(0, LB); int r_key = query(0, RB) - query(0, mid); l_key = mid - LB - l_key, r_key = RB - mid - r_key; if (l_key <= r_key) res = mid, l = mid + 1; else r = mid - 1; } ll k1 = query(1, res) - query(1, LB), k1_ = query(0, res) - query(0, LB); ll k2 = query(1, RB) - query(1, res), k2_ = query(0, RB) - query(0, res); ans[i] = (k1 - k1_ * LB - (k1_ * (k1_ - 1) / 2)) + (k2_ * RB - k2 - (k2_ * (k2_ - 1) / 2)); } for (int i = 1; i <= n; i++) printf("%lld ", inv_f[i] + ans[i]); return 0; }
// CF1268C.cpp
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int MAX_N = 2e5 + 200;

ll n, pi[MAX_N], pos[MAX_N], nodes[2][MAX_N], inv_f[MAX_N], ans[MAX_N];
bool vis[MAX_N];

inline int lowbit(int x) { return x & (-x); }

void update(int id, int x, ll d)
{
    for (; x <= n; x += lowbit(x))
        nodes[id][x] += d;
}

ll query(int id, int x, ll ret = 0)
{
    for (; x > 0; x -= lowbit(x))
        ret += nodes[id][x];
    return ret;
}

int main()
{
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &pi[i]), pos[pi[i]] = i;
    for (int i = 1; i <= n; i++)
    {
        inv_f[i] = inv_f[i - 1] + i - query(0, pos[i]) - 1;
        update(0, pos[i], 1);
    }
    memset(nodes[0], 0, sizeof(nodes[0]));
    ll LB = n, RB = 1;
    for (int i = 1; i <= n; i++)
        update(0, i, 1), update(1, i, i), vis[i] = true;
    for (int i = 1; i <= n; i++)
    {
        LB = min(LB, pos[i]), RB = max(RB, pos[i]);
        update(0, pos[i], -1), update(1, pos[i], -pos[i]), vis[pos[i]] = false;
        int l = LB, r = RB, res = LB;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            int l_key = query(0, mid - 1) - query(0, LB);
            int r_key = query(0, RB) - query(0, mid);
            l_key = mid - LB - l_key, r_key = RB - mid - r_key;
            if (l_key <= r_key)
                res = mid, l = mid + 1;
            else
                r = mid - 1;
        }
        ll k1 = query(1, res) - query(1, LB), k1_ = query(0, res) - query(0, LB);
        ll k2 = query(1, RB) - query(1, res), k2_ = query(0, RB) - query(0, res);
        ans[i] = (k1 - k1_ * LB - (k1_ * (k1_ - 1) / 2)) + (k2_ * RB - k2 - (k2_ * (k2_ - 1) / 2));
    }
    for (int i = 1; i <= n; i++)
        printf("%lld ", inv_f[i] + ans[i]);
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *