蔚来杯2022牛客暑期多校训练营3 AC

比赛链接

A

题解

知识点:LCA。

队友写的,俺不会qwq。预处理出关键点序列的在树A B上的前缀LCA和后缀LCA,枚举去掉的关键节点并使用前后缀LCA算出剩余节点的LCA比较权值即可。

时间复杂度 \(O(k \log n)\)

空间复杂度 \(O(n)\)

代码

#include<bits/stdc++.h>

#define N 400010
#define inf 0x7fffffff

using namespace std;

int n, m, dep[N], fa[N][23], first[N], cnt, ans, w[N];
int ss[N], k, maxk_A[2], mink_A[2], maxx_A[2], minn_A[2] = { inf,inf }, dfsx[N], t;
int maxk_B[2], mink_B[2], maxx_B[2], minn_B[2] = { inf,inf };

struct node {
    int v, next;
}edge[N];

void add(int u, int v) {
    edge[++cnt] = (node){ v,first[u] };
    first[u] = cnt;
}

void dfs(int u, int fath) {
    dep[u] = dep[fath] + 1, fa[u][0] = fath, dfsx[u] = ++t;
    for (int i = 1;i <= (int)log2(dep[u]) + 1;i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for (int i = first[u];i != 0;i = edge[i].next) {
        if (edge[i].v != fath) dfs(edge[i].v, u);
    }
}

int LCA(int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    while (dep[x] > dep[y]) x = fa[x][(int)log2(dep[x] - dep[y])];
    if (x == y) return x;
    for (int i = (int)log2(dep[x]);i >= 0;i--) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1;i <= k;i++) scanf("%d", &ss[i]);
    for (int i = 1;i <= n;i++) scanf("%d", &w[i]);
    for (int i = 1, x;i < n;i++) {
        scanf("%d", &x);
        add(i + 1, x), add(x, i + 1);
    }
    for (int i = 1;i <= n;i++) scanf("%d", &w[i + n]);
    for (int i = 1, x;i < n;i++) {
        scanf("%d", &x);
        add(i + 1 + n, x + n), add(x + n, i + 1 + n);
    }
    dfs(1, 0);
    t = 0, dfs(1 + n, 0);
    for (int i = 1;i <= k;i++) {
        if (dfsx[ss[i]] > maxx_A[0]) { maxk_A[1] = maxk_A[0], maxx_A[1] = maxx_A[0]; maxk_A[0] = ss[i], maxx_A[0] = dfsx[ss[i]]; }
        else if (dfsx[ss[i]] > maxx_A[1]) maxk_A[1] = ss[i], maxx_A[1] = dfsx[ss[i]];
        if (dfsx[ss[i]] < minn_A[0]) { mink_A[1] = mink_A[0], mink_A[1] = minn_A[0]; mink_A[0] = ss[i], minn_A[0] = dfsx[ss[i]]; }
        else if (dfsx[ss[i]] < minn_A[1]) mink_A[1] = ss[i], minn_A[1] = dfsx[ss[i]];
    }
    for (int i = 1;i <= k;i++) {
        if (dfsx[ss[i] + n] > maxx_B[0]) { maxk_B[1] = maxk_B[0], maxx_B[1] = maxx_B[0]; maxk_B[0] = ss[i], maxx_B[0] = dfsx[ss[i] + n]; }
        else if (dfsx[ss[i] + n] > maxx_B[1]) maxk_B[1] = ss[i], maxx_B[1] = dfsx[ss[i] + n];
        if (dfsx[ss[i] + n] < minn_B[0]) { mink_B[1] = mink_B[0], minn_B[1] = minn_B[0]; mink_B[0] = ss[i], minn_B[0] = dfsx[ss[i] + n]; }
        else if (dfsx[ss[i] + n] < minn_B[1]) mink_B[1] = ss[i], minn_B[1] = dfsx[ss[i] + n];
    }
    for (int i = 1;i <= k;i++) {
        int x_A, y_A, x_B, y_B;
        if (ss[i] != maxk_A[0]) x_A = maxk_A[0];
        else x_A = maxk_A[1];
        if (ss[i] != mink_A[0]) y_A = mink_A[0];
        else y_A = mink_A[1];
        if (ss[i] != maxk_B[0]) x_B = maxk_B[0];
        else x_B = maxk_B[1];
        if (ss[i] != mink_B[0]) y_B = mink_B[0];
        else y_B = mink_B[1];
        int a = LCA(x_A, y_A), b = LCA(x_B + n, y_B + n);
        if (w[a] > w[b]) ans++;
    }
    printf("%d", ans);
    return 0;
}
/*
5 2
3 4
6 6 3 4 6
1 2 2 4
7 4 5 7 7
1 1 3 2
*/

C

题解

知识点:贪心,排序。

通过如下比较即可:

sort(s, s + n, [&](string &a, string &b) {
	return a + b < b + a;
});

注意要用引用,否则可能过不去。

时间复杂度 \(O(|S|\log n)\)

空间复杂度 \(O(|S|)\)

代码

#include <bits/stdc++.h>

using namespace std;

string s[2000007];

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0;i < n;i++) cin >> s[i];
    sort(s, s + n, [&](string &a, string &b) {
        return a + b < b + a;
    });
    for (int i = 0;i < n;i++) cout << s[i];
    cout << '\n';
    return 0;
}
posted @ 2022-07-26 22:07  空白菌  阅读(35)  评论(0编辑  收藏  举报