2020牛客暑期多校训练营(第五场)B、D、E、F、I题解及补题

文章目录

  • 2020牛客暑期多校训练营(第五场)题解及补题
    • 比赛过程
    • 题解
      • A
        • 题意
        • 解法
        • 代码
      • B
        • 题意
        • 解法
        • 代码
      • C
        • 题意
        • 解法
        • 代码
      • D
        • 题意
        • 解法
        • 代码
      • E
        • 题意
        • 解法
        • 代码
      • F
        • 题意
        • 解法
        • 代码
      • G
        • 题意
        • 解法
        • 代码
      • H
        • 题意
        • 解法
        • 代码
      • I
        • 题意
        • 解法
        • 代码
      • J
        • 题意
        • 解法
        • 代码
      • K
        • 题意
        • 解法
        • 代码

2020牛客暑期多校训练营(第五场)题解及补题

比赛过程

这场打出了排名新低,总结原因是前期还行中规中矩,后期两个中等难度的签到题罚时炸了。D和E犯了很多低级的错误,其中E不够熟悉大数板子,而且一开始过于急躁随便就觉得是把所有长度乘起来wa了之后才去认真思考,以后可以多花时间验证思想正确性,纯感觉流不太行。E思路正确,代码挫了,码力有待提升。

题解

A

题意
解法
代码
//将内容替换成代码

B

题意

n n n个点的一棵树,可以任意增减边(要求图联通且环的异或和为0),问修改后的树最小权值和。

解法

首先可以注意到,无论如何增删边,不会改变两个点路径的边的异或和,那么我们可以由这个特性给每个点一个权值,答案即为异或最小生成树。计算异或最小生成树主要用到了是 B o r u v k a Boruvka Boruvka算法和01字典树,因为其中有一个求最小异或对的过程,暴力是 n 2 n^2 n2的复杂度, t r i e trie trie可以用来优化第二层循环,因为对于每个数我们可以从高到低的去贪心选择数位一样的数。 B o r u v k a Boruvka Boruvka算法重点在于思想本身,这个算法一般情况下比 p r i m prim prim k r u s k a l kruskal kruskal要麻烦得多不会用但是在边权由两个点点权决定的题里有奇效, b o r u v k a boruvka boruvka相当于是两个思想的结合,多源的去做 p r i m prim prim

代码
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 111;
const ll mod = 1e9 + 7;
#define P pair
int trie[maxn * 32][2], idx;
vector<P> G[maxn];
int val[maxn];
void add(int a) {
   
    int p = 0;
    for (int i = 29; i >= 0; --i) {
   
        bool tp = a & (1 << i);
        if (!trie[p][tp]) trie[p][tp] = ++idx;
        p = trie[p][tp];
    }
}
int query(int a) {
     //查找和a异或最小的数
    int p = 0, ans = 0;
    for (int i = 29; i >= 0; --i) {
   
        bool tp = a & (1 << i);
        if (trie[p][tp]) {
   
            p = trie[p][tp];
        } else {
   
            ans |= (1 << i);
            p = trie[p][!tp];
        }
    }
    return ans;
}
void dfs(int u, int fa) {
   
    for (auto v : G[u]) {
   
        if (v.first == fa) continue;
        val[v.first] = val[u] ^ v.second;
        dfs(v.first, u);
    }
}
ll ans;
void solve(int id, int l, int r) {
   
    if (id < 0) return;
    int mid = l - 1;
    while (mid < r && (val[mid + 1] & (1 << id)) == 0) mid++;
    if (l <= mid) solve(id - 1, l, mid);
    if (mid + 1 <= r) solve(id - 1, mid + 1, r);
    if (l <= mid && mid + 1 <= r) {
   
        for (int i = l; i <= mid; i++) add(val[i]);
        int minn = INT_MAX;
        for (int i = mid + 1; i <= r; i++) minn = min(minn, query(val[i]));

        for (int i = 0; i <= idx; ++i) {
   
            trie[i][0] = trie[i][1] = 0;
        

你可能感兴趣的:(2020牛客组队训练)