ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

10.14训练赛

2021-10-22 12:35:21  阅读:190  来源: 互联网

标签:fu dep ll cin 训练赛 ans 10.14 dis


A. CodeForces 1526D

由D题可以知道交换需要的次数就是目标字符串相对于原字符串的逆序对个数,

想让逆序对个数尽可能多那么相同字符要连在一起,所以只需要枚举全排列即可。

#include <bits/stdc++.h>
#define fu(a, b, c) for (int a = b; a <= c; a++)
#define fd(a, b, c) for (int a = b; a >= c; a--)
using namespace std;
long long t, n, m, ans, f;

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> t;
    while (t--) {
        string s, p = "ANOT", t;
        cin >> s;
        int cnt[100]{};
        for (int c : s) ++cnt[c];
        ans = -1;
        do {
            n = 0;
            string cur = s, T;
            for (char c : p) {
                f = 0;
                T = "";
                for (char x : cur) {
                    if (x == c)
                        n += f;
                    else
                        ++f, T += x;
                }
                cur = T;
            }
            if (n > ans)
                ans = n, t = p;
        } while (next_permutation(&p[0], &p[4]));
        fu(i, 0, 3) while (cnt[t[i]]--) cout << t[i];
        cout << '\n';
    }
}

B. CodeForces 1526C2

显然的反悔贪心。

#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll N = 3e5 + 1, M = 31621;
ll t, n, m, k, a, b, c, d, e, f, l, r, ans;
ll x[N], w[N], y[N], z[N];

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    multiset<ll> s;
    fu(i, 1, n) {
        cin >> a;
        b += a;
        if (a < 0)
            s.insert(a);
        if (b < 0)
            b -= *s.begin(), s.erase(s.begin()), ++c;
    }
    cout << n - c;
}

C. CodeForces 1526E

考虑后缀数组的定义,如果\(rk[sa[i] + 1] > rk[sa[i + 1] + 1]\)那么\(s[i] < s[i + 1]\),

否则\(s[i] <= s[i + 1]\),遍历一遍就得到了所有相邻字符间的关系,剩下就是一个组合数学

的问题,可以考虑对应的差分数组用隔板法解决。

#include <bits/stdc++.h>
#define fu(a, b, c) for (int a = b; a <= c; a++)
#define fd(a, b, c) for (int a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 2e5 + 1, M = 998244353;
ll t, n, m, k, ans;
ll a, b = 1, c, d, e = -1e7;
ll x[N], y[N], z[N], v[N];
ll sa[N], rk[N];
string s;

inline ll inv(ll x) {
    return x ^ 1 ? (M - M / x) * inv(M % x) % M : 1;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n >> k;
    fu(i, 1, n) cin >> sa[i], rk[sa[i]] = i;
    c = ans = 1, m = n;
    fu(i, 1, n - 1) c += rk[sa[i] + 1] > rk[sa[i + 1] + 1], m = m * i % M;
    a = n + k - c;
    fu(i, 0, n - 1) ans = ans * (a - i) % M;
    cout << ans * inv(m) % M;
}

D. CodeForces 1430E

将原串每个字符替换成其在目标串中的位置,就得到了一个排列,每次交换相邻元素可以
减少一个这个排列的逆序对,而我们的目标是清空逆序对,所以统计逆序对个数即可。

def cal(l, r):
    if(l == r):
        return
    m = l + r >> 1
    cal(l, m), cal(m + 1, r)
    l1 = l; l2 = m + 1; c = l
    global ans
    while l1 <= m and l2 <= r:
        if a[l1] < a[l2]:
            b[c] = a[l1]
            l1 += 1
            ans += l2 - m - 1
        else:
            b[c] = a[l2]
            l2 += 1
        c += 1
    while l1 <= m:
        b[c] = a[l1]
        ans += l2 - m - 1
        l1 += 1
        c += 1
    while l2 <= r:
        b[c] = a[l2]
        l2 += 1
        c += 1
    a[l : r + 1] = b[l : r + 1]

n = int(input())
s = input()
v = [[] for i in range(26)]
p = [0] * 26
for i in range(n):
    v[ord(s[i]) - 97].append(i)

a = [0] * n; b = [0] * n
for i in range(n - 1, -1, -1):
    c = ord(s[i]) - 97
    a[n - 1 - i] = v[c][p[c]]
    p[c] += 1
ans = 0
cal(0, n - 1)
print(ans)

E. CodeForces 1428D

贪心构造。

input()
c2, c3, ans = [], [], []
k = [c2, c3]
for i, x in enumerate(map(int, input().split()), 1):
    if x == 1:
        if c2:
            ans += [(c2.pop(), i)]
        elif c3:
            ans += [(c3.pop(), i), (i, i)]
        else:
            ans += [(i, i)]
    elif x != 0:
        ans += [(i, i)]
        if c3:
            ans += [(c3.pop(), i)]
        k[x-2] += [i]
if c2 or c3:
    print(-1)
else:
    print(len(ans))
    for i in ans:
        print(*i)

F. HDU 4871

最短路建树然后点分治。

#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
const ll N = 1e5 + 10;
ll t, n, m, k, rt, mxd, mdc;
ll dis[N], c[N]{0, 1}, d[N];
ll pre[N], sz[N], mx[N]{N};
bool vis[N];
vector<pll> g[N], G[N];

void get_rt(ll u, ll f, ll tot) {
    sz[u] = 1, mx[u] = 0;
    for (auto i : g[u]) {
        ll v = i.first;
        if (v ^ f && !vis[v]) {
            get_rt(v, u, tot);
            sz[u] += sz[v];
            mx(mx[u], sz[v]);
        }
    }
    mx(mx[u], tot - sz[u]);
    if (mx[u] < mx[rt])
        rt = u;
}

void upd(ll u, ll f, ll dis, ll dep, bool F) {
    if (dep == k)
        return;
    if (F) { // 当前子树所有节点的贡献计算完后再更新
        // 每次只计算经过根节点的路径,所以把之前子树中每个dep对应最大dis和数量存起来
        if (dis > d[dep + 1])
            d[dep + 1] = dis, c[dep + 1] = 1;
        else if (dis == d[dep + 1])
            ++c[dep + 1];
    } else if (c[k - dep]) {
        if (dis + d[k - dep] > mxd)
            mxd = dis + d[k - dep], mdc = c[k - dep];
        else if (dis + d[k - dep] == mxd)
            mdc += c[k - dep];
    }
    for (auto i : g[u]) {
        ll v = i.first, w = i.second;
        if (v ^ f && !vis[v])
            upd(v, u, dis + w, dep + 1, F);
    }
}

void go(ll u) {
    vis[u] = 1;
    // d[1] = 0, c[1] = 1
    memset(d + 2, 0, k - 2 << 3);
    memset(c + 2, 0, k - 2 << 3);
    for (auto i : g[u]) {
        ll v = i.first, w = i.second;
        if (!vis[v])
            upd(v, u, w, 1, 0), upd(v, u, w, 1, 1);
    }
    for (auto i : g[u]) {
        ll v = i.first;
        if (!vis[v])
            rt = 0, get_rt(v, 0, sz[v]), go(rt);
    }
}

inline void dij() {
    memset(dis + 1, 60, n * 8), dis[1] = 0;
    priority_queue<pll, vector<pll>, greater<pll>> q;
    q.emplace(0, 1);
    ll u, v, d;
    while (q.size()) {
        pll t = q.top();
        d = t.first, u = t.second, q.pop();
        if (d > dis[u])
            continue;
        if (v = pre[u]) {
            g[v].emplace_back(u, d - dis[v]);
            g[u].emplace_back(v, d - dis[v]);
        }
        for (auto i : G[u]) {
            ll v = i.first, w = i.second, nxd = dis[u] + w;
            if (nxd < dis[v] || nxd == dis[v] && u < pre[v])
                q.emplace(nxd, v), pre[v] = u, dis[v] = nxd;
        }
    }
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> t;
    ll u, v, w;
    while (t--) {
        cin >> n >> m >> k;
        fu(i, 1, n) g[i].clear(), G[i].clear();
        memset(vis + 1, 0, n);
        fu(i, 1, m) {
            cin >> u >> v >> w;
            G[u].emplace_back(v, w);
            G[v].emplace_back(u, w);
        }
        dij();
        rt = mxd = mdc = 0, get_rt(1, 0, n), go(rt);
        cout << mxd << ' ' << mdc << '\n';
    }
}

G. CodeForces 1426B

900分的签到题,然鹅我当初还被hack了。

#include <bits/stdc++.h>
#define fu(a, b, c) for (int a = b; a <= c; a++)
#define fd(a, b, c) for (int a = b; a >= c; a--)
using namespace std;
bool f[101], f1[101];

int main() {
    int t, n, m, a, b, c, d;
    scanf("%d", &t);
    while (t--) {
        memset(f, 0, sizeof f);
        memset(f1, 0, sizeof f1);
        bool flag = 0;
        scanf("%d%d", &n, &m);
        fu(i, 1, n) {
            scanf("%d%d%d%d", &a, &b, &c, &d);
            falg |= b == c;
        }
        printf("%s\n", m & 1 || !flag ? "NO" : "YES");
    }
}

标签:fu,dep,ll,cin,训练赛,ans,10.14,dis
来源: https://www.cnblogs.com/lemu/p/15438214.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有