• Codeforces Round #683 (Div. 2, by Meet IT) E


    Codeforces Round #683 (Div. 2, by Meet IT) E

    大意

    给你 (n) 个各不相同的数,写在 (n) 个点上。

    记写在第 (i) 个点上的数为 (a_i) ,则对于任意点 (i) 会与使 (a_ioplus a_j) 最小化的点 (j) 连一条无向边。 (oplus) 代表异或

    如果两个点互相连边只计算一条。

    问你最少去掉几个点之后能让剩下的图为一颗树。

    思路

    好巧妙的题...

    1. 原图一定是树或森林,不可能出现环。

      证:

      不失一般性,如果存在环,我们将环取出,重新标号为 (1,...,k) ,规定 (a) 连向 (a+1)(k) 连向 (1)

      考虑 (1 ightarrow2) 的边,按照规定,因为有 (2 ightarrow 3) ,所以 $ a_2oplus a_3 < a_1oplus a_2$ 。

      考虑 (3 ightarrow 4 ...) 显然最后有 (a_koplus a_1 < a_{k-1}oplus a_k < ... <a_1oplus a_2)(a_1oplus a_2 < a_1oplus a_k) ,所以不难发现这个环是非法的。

      也就是说按照题述规则链接不会出现环。

    2. (a_i) 按照二进制下最大的 (1) 的位置分为两个集合 (S_0, S_1)

      (exists k ; s_iin S_1,s_jin S_0 ;s_j<2^kleq s_i<2^{k+1})

      可以发现此时若 (|S_0|>1 and |S_1|>1) 那么原图一定不是一棵树。

      因为两个集合的点只会与和自己处于相同集合内的点连边。

      因为最少删除就是最多保留。

      所以我们最多只能让其中一个集合保留一个点,另外一个保留尽量多的点。

      (R(S_i)) 为该集合最多保留的点, (S_j,S_k)(S_i) 在上述分法下的子集。

      按照上述分法,两个子集的最多可以保留的点的数量是互不影响的,因为它们之间在元素数量都大于一时不可能有边。

      如果有一个集合元素数量等于一而另一个不为零,那么那一个元素肯定连向另一个集合里的元素,此时依然要保证另一个集合里的元素保留的尽量多。

      如果一个集合为零,那么肯定不用考虑他了,另一个集合也要尽量保留的多。

      那么当 (R(S_j) eq 0 and R(S_k) eq 0) ,能发现 (R(S_i) = max(R(S_j),R(S_k))+1)

      如果 (R(S_j) = 0) 那么 (R(S_i) = R(S_k))

      于是我们可以递归处理这个问题了。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    #define ll long long
    #define ull unsigned long long
    #define cint const int&
    #define Pi acos(-1)
    
    const int mod = 998244353;
    const int inf_int = 0x7fffffff;
    const ll inf_ll = 0x7fffffffffffffff;
    const double ept = 1e-9;
    
    int n;
    int a[200100];
    
    int dfs(cint l, cint r, cint num, int key) {
        if(l > r) return 0;
        if(l == r) return 1;
        int k = lower_bound(a+1, a+1+n, key+(1<<num)) - a;
        int x = dfs(l, k-1, num-1, key);
        int y = dfs(k, r, num-1, key+(1<<num));
        if(!(x*y)) return max(x, y);
        return max(x,y) + 1;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n;
        for(int i=1; i<=n; i++) cin >> a[i];
        sort(a+1, a+1+n);
        int t=0;
        while((1<<t) <= a[n]) ++t;
        cout << n-dfs(1, n, t-1, 0);
        return 0;
    }
    
  • 相关阅读:
    阿里云快速搭建Node.js开发环境
    初始化阿里云服务器
    docker上安装tomcat
    阿里云搭建支付宝小程序
    阿里云docker上安装redis
    WARN o.a.c.c.AprLifecycleListener [log,175] The Apache Tomcat Native library failed to load. The error reported was [no tcnative1 in java.library.path:
    阿里云快速搭建网站
    云服务器(CentOS系统)完全卸载mysql
    wumeismart编译运行和部署系统
    阿里云ssh关闭,保持jar程序运行
  • 原文地址:https://www.cnblogs.com/ullio/p/14016570.html
Copyright © 2020-2023  润新知