• 2021牛客暑期多校训练营4 个人补题记录


    比赛链接:Here

    1001 - Course

    1002 - Sample Game

    1003 - LCS

    构造,

    首先排除不可能的情况

    • 两个 LCS 的值减去最小的 LCS 值如果比 (n) 还大,那么肯定构造不出来啊(不够长

    剩下就是对于公共的 min(a,b,c)a ,对应的三种情况分别赋予 b,c,d 如果还是不够 (n) 则赋予不同值即可

    Show Code
    
    
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int a, b, c, d, n;
        cin >> a >> b >> c >> n;
        d = min({a, b, c});
        string s1, s2, s3;
        if (a + c - d > n || a + b - d > n || b + c - d > n) {cout << "NO" << endl; return 0;}
        for (int i = 1; i <= d; i++) s1 += 'a', s2 += 'a', s3 += 'a';
        for (int i = 1; i <= a - d; i++) s1 += 'b', s2 += 'b';
        for (int i = 1; i <= b - d; i++) s2 += 'c', s3 += 'c';
        for (int i = 1; i <= c - d; i++) s1 += 'd', s3 += 'd';
        while (s1.size() < n) s1 += 'e';
        while (s2.size() < n) s2 += 'f';
        while (s3.size() < n) s3 += 'g';
        cout << s1 << endl << s2 << endl << s3 << endl;
    }
    

    1004 - Rebuild Tree

    1005 - Tree Xor

    1006 - Just a joke

    讨论区有人提出

    有两种操作:

    1. 删除一条边(边的数目-1)
    2. 删除个连通分量 (点的数目-k,边的数目-(k-1))

    所以每次操作边和点的奇偶性都会变化,所以只需要判断边加点和的奇偶性即可。

    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n, m;
        cin >> n >> m;
        int x, y;
        for (int i = 0; i < m; i++) cin >> x >> y;
        if ((n + m) & 1) puts("Alice");
        else puts("Bob");
    }
    

    在赛时队友想到了用并查集求连通块量 + 单独的点的奇偶性

    const int N = 10010;
    int f[N], ans;
    int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);}
    void merge(int x, int y) {
        x = find(x), y = find(y);
        if (x != y) f[y] = x;
        else ++ans;
    }
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) f[i] = i;
        for (int i = 0, x, y; i < m; ++i) {
            cin >> x >> y;
            merge(x, y);
        }
        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            if (f[i] == i) cnt++;
        }
        cout << ((ans + cnt) % 2 == 0 ? "Bob
    " : "Alice
    ");
    }
    

    1007 - Product

    1008 - Convolution

    1009 - Inverse Pair

    对原数组处理以后求个逆序对即可

    (a) 数组中选择合适的 (b_i in {0,1}) 来最小化逆序对数

    求逆序对的方法有树状数组和归并排序,这里写归并排序简单一点

    同时一定要开 long long 防止溢出

    Show Code
    
    
    using ll = long long;
     
    const int N = 2e5 + 10;
    ll a[N], tmp[N], n;
    int vis[N];
    ll ans = 0;
    void Merge(int l, int m, int r) {
        int i = l;
        int j = m + 1;
        int k = l;
        while (i <= m && j <= r) {
            if (a[i] > a[j]) {
                tmp[k++] = a[j++];
                ans += m - i + 1;
            } else
                tmp[k++] = a[i++];
        }
        while (i <= m) tmp[k++] = a[i++];
        while (j <= r) tmp[k++] = a[j++];
        for (int i = l; i <= r; i++) a[i] = tmp[i];
    }
    void M_sort(int l, int r) {
        if (l < r) {
            int m = (l + r) >> 1;
            M_sort(l, m);
            M_sort(m + 1, r);
            Merge(l, m, r);
        }
    }
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            if (vis[a[i] + 1] == 1) {
                a[i] += 1, vis[a[i] + 1] = 2;
            }  else vis[a[i]] = 1;
        }
        // for (int i = 1; i <= n; ++i) cout << a[i] << " 
    "[i == n];
        M_sort(1, n);
        cout << ans << "
    ";
    }
    

    1010 - Average

    为什么连板子都没看出来啊?明明比赛前一天还复习了单调队列优化DP的题

    (a_{1...n})(b_{i...m}) 构成的数组形成的 (n imes m) 的矩阵求至少长度为 (x imes y) 的最大值子矩阵

    我们要求至少长度为 (x imes y) 的最大值子矩阵,转化过来就是求出 (a_{1...n})(b_{i...m}) 中找一个最长的连续一段区间使其平均值最大。最后两者相加即可


    二分答案平均值。

    judge时把每一个a[i]-mid得到b[i]

    在b[i]中找到一段合法的串使其权值和最大。

    当最大权值和大于等于0时则mid上移。

    求最大权值和用单调队列就行。(预处理b[i]的前缀和sum[i],队列中记录当前位置可选区间的最小的sum[i])

    核心代码参考:Here

    bool check(double x) {
        int i, l = 1, r = 0;
        for (i = 1; i <= n; i++)
            a[i] = (double)b[i] - x;
        sum[0] = 0;
        for (i = 1; i <= n; i++)
            sum[i] = sum[i - 1] + a[i];
        for (i = 1; i <= n; i++) {
            if (i >= s) {
                while (r >= l && sum[i - s] < sum[q[r]])r--;
                q[++r] = i - s;
            }
            if (l <= r && q[l] < i - t)l++;
            if (l <= r && sum[i] - sum[q[l]] >= 0)return true;
        }
        return false;
    }
    int main() {
        ...
        int ans = l = -10000; r = 10000;
        while (r - l > 1e-5) {
            mid = (l + r) / 2;
            if (check(mid)) ans = l = mid;
            else r = mid;
        }
        printf("%.3lf
    ", ans);
        return 0;
    }
    

    【AC Code】

    Show Code
    
    
    const int N = 1e5 + 10;
    int pi[N];
    double pp[N];
    double solve(int k, int a) {
        double l = 0.0, r = 100001.0;
        for (int i = 1; i <= k; ++i) cin >> pi[i];
        while (r - l > 1e-8) {
            double m = (l + r) / 2.0, p = 0.0, sum = 0;
            for (int i = 1; i <= a; ++i) pp[i] = pp[i - 1] + pi[i] - m;
            sum = pp[a];
            for (int i = a + 1; i <= k; ++i) {
                p = min(p, pp[i - a]);
                pp[i] = pp[i - 1] + pi[i] - m;
                sum = max(sum, pp[i] - p);
            }
            if (sum >= 0) l = m;
            else r = m;
        }
        return r;
    }
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n, m, a, b;
        cin >> n >> m >> a >> b;
        cout << fixed << setprecision(10) << (solve(n, a) + solve(m, b));
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    WCF客户端链接服务超时客户端close
    C# byte数组常用扩展浅析(转)
    代码生成相关工具及技术
    已处理证书链,但是在不受信任提供程序信任的根证书中终止。
    清理SQL Server数据库日志的两种方法
    开源框架项目列表
    SQL Server数据库文件恢复技术
    VS2008找不到导出模板
    jquery 学习笔记(二)
    方法的参数的默认值设置
  • 原文地址:https://www.cnblogs.com/RioTian/p/15085177.html
Copyright © 2020-2023  润新知