• nowcoder 2020 多校 第五场


    nowcoder 2020 多校 第五场

    https://ac.nowcoder.com/acm/contest/5670

    B Graph

    tire树,最小生成树

    题意

    给一个带有边权的树,可以删除或添加边,但要保证:

    • 图联通
    • 环上边权异或为0

    Solution

    不管怎么操作,两点路径上边权的异或值是固定的,于是问题就转化成一个最小生成树问题。每次选出不联通的点集(S_1), (S_2),
    将他们联通的代价是

    [ minlimits_{uin S_1 vin S_2} {mathord{dis}(u,v)} ]

    可以通过tire树实现这个过程,就是tire树合并子节点,复杂度为(O(nlog n))

    #include <cstdio>
    #include <stack>
    #include <set>
    #include <cmath>
    #include <map>
    #include <time.h>
    #include <vector>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <memory.h>
    #include <cstdlib>
    #include <queue>
    #include <iomanip>
    #include <bitset>
    #include <unordered_map>
    #include <assert.h>
    #define P pair<int, int>
    #define LL long long
    #define LD long double
    #define PLL pair<LL, LL>
    #define mset(a, b) memset(a, b, sizeof(a))
    #define rep(i, a, b) for (int i = a; i < b; i++)
    #define PI acos(-1.0)
    #define random(x) rand() % x
    #define debug(x) cout << #x << " " << x << "
    "
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const LL __64inf = 0x3f3f3f3f3f3f3f3f;
    #ifdef DEBUG
    const int MAX = 1e3 + 50;
    #else
    const int MAX = 3e6 + 50;
    #endif
    const int mod = 10007;
    
    LL pow2[100];
    vector<P> G[MAX];
    int dis[MAX];
    struct Tire{
        int nex[MAX][2];
        int siz[MAX];
        int tot ;
        LL ans;
        void init(){
            ans = 0;
            siz[0] = 0;
            mset(nex[0], 0);
            tot = 1;
        }
        void add(int x, int d) {
            int rt = 0;
            for(int i = d; i >= 0; i--){
                int e = x & pow2[i] ? 1 : 0;
                if(!nex[rt][e]) {
                    mset(nex[tot], 0);
                    siz[tot] = 0;
                    nex[rt][e] = tot ++;
                }
                rt = nex[rt][e];
                siz[rt] ++;
            }
        }
        LL query(int val, int u, int d) {
            int rt = u;
            LL res = val;
            for(int i = d; i >= 0; i--){
                if(res & pow2[i]) {
                    if(nex[rt][1]) {
                        res ^= pow2[i];
                        rt = nex[rt][1];
                    }
                    else rt = nex[rt][0];
                }
                else {
                    if(nex[rt][0]) {
                        rt = nex[rt][0];
                    }
                    else {
                        res ^= pow2[i];
                        rt = nex[rt][1];
                    }
                }
            }
            return res;
        }
        LL merge(int l, int r, int val, int d, int row_d){
            if(!nex[l][0] and !nex[l][1]) {
                return query(val, r, row_d);
            }
            LL res = inf;
            if(nex[l][0]) res = min(res, merge(nex[l][0], r, val, d-1, row_d));
            if(nex[l][1]) res = min(res, merge(nex[l][1], r, val^pow2[d], d-1, row_d));
            return res;
        }
        void dfs(int u, int val, int d) {
            if(nex[u][0]) dfs(nex[u][0], val, d-1);
            if(nex[u][1]) dfs(nex[u][1], val ^ pow2[d], d-1);
            if(!nex[u][0] or !nex[u][1]) 
                return;
            int l = nex[u][0], r = nex[u][1];
            if(siz[l] > siz[r]) swap(l, r);
            ans += 1LL * merge(l, r, 0, d-1, d-1) + pow2[d];
    
        }
    }tire;
    void dfs(int u, int p, int d){
        dis[u] = d;
        for(int i = 0; i < G[u].size(); i++){
            int v = G[u][i].first;
            if(v == p) continue;
            dfs(v, u, d^G[u][i].second);
        }
    }
    int main(){
    #ifdef DEBUG
        freopen64("in", "r", stdin);
    #endif
        pow2[0] = 1;
        for(int i = 1; i < 32; i++) pow2[i] = pow2[i-1] << 1;
        int n;
        scanf("%d", &n);
        for(int i = 1; i < n; i++) {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            u++, v++;
            G[u].emplace_back(v, c);
            G[v].emplace_back(u, c);
        }
        dfs(1, -1, 0);
        tire.init();
        for(int i = 1; i <= n; i++) 
            tire.add(dis[i], 29);
        tire.dfs(0, 0, 29);  
        printf("%lld
    ", tire.ans);
        return 0;
    }
    

    D Drop Voicing

    最长上升子序列

    题意

    给一个序列(p_1dots p_n),可以进行两种操作,进行连续的第一个操作耗费一个代价

    • (p_{n-1})放到最前面
    • (p_1)放到最后面

    求把序列变成升序的最小代价

    Solution

    结合两种操作其实就是把一个元素(p_i)移到一个位置,需要一个代价。于是变成求LIS

    int n;
    int a[MAX];
    int b[MAX];
    int solve(){
        mset(b, 0);
        int ans = 0;
        for(int i = 1; i <= n; i++) {
            int idx = lower_bound(b, b+ans, a[i]) - b;
            b[idx] = a[i];
            if(idx == ans) ans ++;
        }
        // cout << n - ans << "
    ";
        return ans;
    }
    int main(){
    #ifdef DEBUG
        freopen64("in", "r", stdin);
    #else 
        ios::sync_with_stdio(0);
        cin.tie(0);
    #endif
        cin >> n;
        for(int i = 1; i <= n; i++) cin >> a[i];
        int ans = 0;
        for(int i = 0; i < n; i++) {
            rotate(a+1, a+2, a+n+1);
            ans = max(ans, solve());
        }
        cout << n - ans << "
    ";
        return 0;
    }
    

    E Bogo Sort

    题意

    给一个置换,求有多少种排列可以通过这个置换变成升序

    from math import gcd
    
    def lcm(a:int, b:int) ->int:
        return a * b // gcd(a, b)
    
    n = int(input())
    a = [0] + list(map(int, input().split()))
    vis = [False for i in range(len(a))]
    
    ans = 1
    for i in range(1, n+1):
        x = a[i]
        if vis[x] : continue
        cur = 0
        while not vis[x] :
            vis[x] = True
            cur += 1
            x = a[x]
        ans = lcm(ans, cur)
    print(ans)
    
    
  • 相关阅读:
    git各种操作:基本操作 and 多人协作 and 冲突解决
    mini-ndn0.5.0 安装教程 (避免踩坑)
    ubuntu18.04 更换镜像源
    自定义日志轮转
    linux常用命令
    Thinkphp6 + uniapp框架,接口访问跨域问题
    机器学习-主成分分析PCA与奇异值分解SVD
    机器学习-数据预处理&特征工程
    机器学习-梯度提升树(xgboost)
    github打不开怎么办
  • 原文地址:https://www.cnblogs.com/sidolarry/p/13453700.html
Copyright © 2020-2023  润新知