Codeforces Round 875 (Div. 2)A~E

A. Twin Permutations

题意:

给一个长度为n的排列a,求另外一个长度为n的排列b,使a[1]+b[1]<=a[2]+b[2]<=…。

思路:

让a最大对应最小,最小对于最大即可,这样所以a[i]+b[i]都是相等的。

代码:

int n, a[maxn], id1[maxn];
int b[maxn], id2[maxn];

bool cmp1(int i, int j) {
    return a[i] < a[j];
}

bool cmp2(int i, int j) {
    return a[i] > a[j];
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++)    cin >> a[i], id1[i] = id2[i] = i;
    sort(id1 + 1, id1 + n + 1, cmp1);
    sort(id2 + 1, id2 + n + 1, cmp2);
    for (int i = 1; i <= n; i++)    b[id1[i]] = a[id2[i]];
    for (int i = 1; i <= n; i++)    cout << b[i] << ' ';
    cout << endl;
}

B. Array merging

题意:

给出两个长度为n的数组a,b,现在每次可以取出任意一个数组的第一个元素,放到c数组的后面,c数组一开始为空,求c数组连续相等的最长子串长度。

思路:

这里可以用两个map把a,b数组每个元素对应的连续相等的最长子串的长度存起来,然后找到最大值即可,具体看代码。

代码:

int n, a[maxn], b[maxn];

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++)    cin >> a[i];
    for (int i = 1; i <= n; i++)    cin >> b[i];
    map<int, int> mp1, mp2;
    for (int i = 1; i <= n; i++) {
        int cnt = 1;
        while (i + 1 <= n && a[i] == a[i + 1])  cnt++, i++;
        mp1[a[i]] = max(mp1[a[i]], cnt);
    }
    for (int i = 1; i <= n; i++) {
        int cnt = 1;
        while (i + 1 <= n && b[i] == b[i + 1])  cnt++, i++;
        mp2[b[i]] = max(mp2[b[i]], cnt);
    }
    int ans = 0;
    for (auto p : mp1)  ans = max(ans, p.second + mp2[p.first]);
    for (auto p : mp2)  ans = max(ans, p.second + mp1[p.first]);
    cout << ans << endl;
}

C. Copil Copac Draws Trees

题意:

给一个有n个节点的数,现在建树,要求当前边的两个点必须有一个点已经绘制完成,从1号点开始。如果两个点都未绘制过,则开始一次新的操作,问建成这棵树需要的操作数。

思路:

其实就是模拟键边的顺序,先把每条边的序号记下来,然后对1号点的儿子进行dfs,如果对于每个点,如果当前点接入图的边的序号在其儿子节点之后,则操作数要加一。

代码:

int n;

int dfs(int u, int fa, vector<vector<int>>& g, map<pair<int, int>, int>& mp) {
    int ans = 0;
    for (auto p : g[u]) {
        if (p == fa)    continue;
        ans = max(ans, (mp[{fa, u}] > mp[{u, p}]) + dfs(p, u, g, mp));
    }
    return ans;
}

void solve() {
    cin >> n;
    vector<vector<int>> g(n + 1, vector<int>());
    map<pair<int, int>, int> mp;
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        cin >> u >> v;
        mp[{u, v}] = i;
        mp[{v, u}] = i;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int ans = 0;
    for (auto p : g[1]) ans = max(ans, dfs(p, 1, g, mp));
    cout << ans + 1 << endl;
}

D. The BOSS Can Count Pairs

题意:

给定两个数组a和b,长度均为n。
要求找到【i,j】的对数,使得1<=i<j<=n&&a[i]*a[j]==b[i]+b[j]。

思路:

对于每个a[i]记录与它对应的b[i]。然后枚举a[i],用f数组记录每个选择的贡献,先求相同a[i]对应的b[i]的贡献,再求不同的贡献,注意每个循环最后f数组的处理。

代码:

int n, a[maxn], b[maxn], f[maxn];
vector<int> v[maxn];

void solve() {
    cin >> n;
    for (int i = 1; i <= n * 2; i++)    v[i].clear();
    for (int i = 1; i <= n; i++)    cin >> a[i];
    for (int i = 1; i <= n; i++)    cin >> b[i], v[a[i]].push_back(b[i]);
    int ans = 0;
    for (int x = 1; x * x <= 2 * n; x++) {
        for (auto j : v[x]) {
            ans += x * x - j > 0 ? f[x * x - j] : 0;
            f[j] ++;
        }
        for (int y = x + 1; x * y <= 2 * n; y++)
            for(auto j : v[y])
                ans += x * y - j > 0 ? f[x * y - j] : 0;
        for (auto j : v[x]) f[j] --;
    }
    cout << ans << endl;
}

E. Hyperregular Bracket Strings

题意:

给出n和k,有k组区间l,r,要求满足每个区间都是匹配的括号序列,且自己整体也是一个匹配的括号序列,长度为n,求满足条件的括号序列的数量,答案对998244353取模。

思路:

匹配的括号序列的数量即卡特兰数,先用异或一个随机数来标记区间,然后利用异或前缀和来记录每个位置的贡献。具体看代码。

tips:

随机数获取:

mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());

头文件:

#include <random>
#include <chrono>

代码

mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());

int n, a[maxn];
int m;
int fac[maxn], infac[maxn];
int f[maxn];

void solve() {
    map<int, int> mp;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)    a[i] = 0;
    while (m--) {
        int l, r;
        int x = rnd();
        cin >> l >> r;
        a[l] ^= x;
        a[r + 1] ^= x;
    }
    for (int i = 1; i <= n; i++)    a[i] ^= a[i - 1], mp[a[i]] ++;
    f[0] = 1; for (int i = 1; i <= n; ++i)if (i % 2 == 0)f[i] = fac[i] * infac[i / 2] % mod * infac[i / 2] % mod * qmi(i / 2 + 1, mod - 2, mod) % mod;
    int ans = 1;
    for (auto i : mp)   ans = ans * f[i.second] % mod;
    cout << ans << endl;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方哲Beans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值