9.26 pony.ai小马智行ak代码

1. 排序贪心

易得,相邻元素尽可能相邻结果最优。O(nlong)

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    typedef long long ll;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    ll res = 0;
    for (int i = 0; i < n - 1; i++) {
        res += (a[i] - a[i + 1]) * (a[i] - a[i + 1]);
    }
    cout << res << endl;
    return 0;
}

2. 二分+滑窗

二分解,如果当前可以,那么尝试更小的O(NlogN)

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

bool isvalid(string &s, int m) {
        vector<int> a(26, 0);
        vector<bool> ok(26, false);
        bool flag = false;
        for (int i = 0; i < m; i++) {
            a[s[i] - 'a']++;
        }
        for (int i = 0; i < 26; i++) {
            if (a[i] > 0) {
                ok[i] = true;
            }
        }
        for (size_t i = m; i < s.size(); i++) {
            int idx = s[i - m] - 'a';
            a[idx]--;
            a[s[i] - 'a']++;
            if (a[idx] == 0) {
                ok[idx] = false;
            }
        }
        for (int i = 0; i < 26; i++) {
            if (ok[i]) {
                flag = true;
            }
        }
        return flag;
}

int main() {
    string s;
    cin >> s;
    int n = s.size();
    int l = 0;
    int r = n;
    while (l < r) {
        int m = l + (r - l) / 2;
        bool flag = isvalid(s, m);
        if (flag) {
            r = m;
        } else {
            l = m + 1;
        }
    }
    if (isvalid(s, l)) cout << l << endl;
    else cout << l + 1<< endl;
    return 0;
}

3. 并查集

相邻的合并,最后找同一root下的最小代价的就可以,近似O(N)

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

struct UF{
    UF(int n) {
        fa = vector<int>(n);
        for (int i = 0; i < n; i++) fa[i] = i;
    }
    int find(int x) {
        if (fa[x] == x) return fa[x];
        fa[x] = find(fa[x]);
        return fa[x];
    }
    void join(int x, int y) {
        int rootx = find(x);
        int rooty = find(y);
        if (rootx == rooty) return;
        fa[rootx] = rooty;
    }
    vector<int> fa;
};

int main() {
    int n, m;
    cin >> n >> m;
    UF uf(n + 1);
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;
        uf.join(x, y);
    }
    int res = 0;
    unordered_map<int, int> mp;
    for (int i = 1; i <= n; i++) {
        int root = uf.find(i);
        if (mp.find(root) == mp.end()) {
            mp[root] = a[i];
        } else {
            mp[root] = min(mp[root], a[i]);
        }
    }
    for (auto &it : mp) {
        res += it.second;
    }
    cout << res << endl;
    return 0;
}

4 组合数+dp

dp[i] 表示 从第0个到第i个数一共多少可能,

不取第i个数,那么就是dp[i - 1]

取第i个数,那么我们分别枚举起点第j 个起点 j 取 [0, i)
如果[j ... i]的某个序列是ok的,那么这个序列的长度一定是 a[j] + 1,
又j和i是必须取的,所以只需在[j, i] 中取 a[j] - 1 个数, 这就是组合数
然后再乘上dp[j - 1] 因为前面有这么多种可能。
这种做法是不会重复的,可以证明,但懒得敲了qaq..

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    vector<vector<int>> c(1005, vector<int>(1005, 0));
    c[0][0] = 1;
    const long long MOD = 998244353;
    for (int i = 1; i <= 1002; i++) {
        for (int j = 0; j <= i; j++) {
            c[i][j] = c[i - 1][j] + (j >= 1 ? c[i - 1][j - 1] : 0);
            c[i][j] = c[i][j] % MOD;
        }
    }
    vector<int> dp(n);
    for (int i = 1; i < n; i++) {
        dp[i] = dp[i - 1];
        for (int j = 0; j < i; j++) {
            if (a[j] >= 1) {
                dp[i] = (dp[i] + (1ll * c[i - j - 1][a[j] - 1] * (j == 0 ? 1 : dp[j - 1] + 1) % MOD)) % MOD;
            }
        }
    }
    cout << dp[n - 1] << endl;

    return 0;
}

注意long long,血坑

#小马智行##笔经##笔试题目#
全部评论
点赞 回复 分享
发布于 2021-09-27 10:15

相关推荐

点赞 评论 收藏
分享
11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
11-20 17:33
已编辑
门头沟学院 嵌入式工程师
小米汽车 底软测开岗 n*15(15大概率拿不到) 双非硕
点赞 评论 收藏
分享
4 15 评论
分享
牛客网
牛客企业服务