zoukankan      html  css  js  c++  java
  • Codeforces Global Round 13

    Codeforces Global Round 13

    A - K-th Largest Value

    int a[N];
     
    int main() {
        IOS; cin >> n >> m;
        rep (i, 1, n) cin >> a[i], k += a[i];
        rep (i, 1, m) {
            int op, x; cin >> op >> x;
            if (op == 1) {
                a[x] ^= 1;
                if (a[x]) ++k;
                else --k;
            } else {
                cout << (k >= x ? 1 : 0) << '
    ';
            }
        }
        return 0;
    }
    
    ## B - Minimal Cost
    
    ```c++
    int main() {
        IOS;
        for (cin >> _; _; --_) {
            ll u, v, ans = 2e9; cin >> n >> u >> v;
            rep (i, 1, n) cin >> a[i];
            rep (i, 2, n) {
                if (a[i] == a[i - 1]) umin(ans, v + min(u, v));
                else if (abs(a[i] - a[i - 1]) == 1) umin(ans, min(u, v));
                else ans = 0;
            }
            cout << ans << '
    ';
        }
        return 0;
    }
    

    C - Pekora and Trampoline

    差分, 可以用树状优化, 没必要

    int main() {
        IOS;
        for (cin >> _; _; --_) {
            cin >> n; ll ans = 0;
            rep (i, 1, n) cin >> a[i], b[i] = 0;
    	rep (i, 1, n) {
                ans += max(a[i] - 1 - b[i], 0);
    	    rep (j, i + 2, min(i + a[i], n)) ++b[j];
    	    b[i + 1] += max(b[i] - a[i] + 1, 0);
    	}
    	cout << ans << "
    ";
        }
        return 0;
    }
    

    D - Zookeeper and The Infinite Zoo

    每次都可以将 u 的二进制上的1向左移或将相邻的1替换成1个1, 第0位补0, 即我们可以将 u 末尾的1 任意左移或消去

    当从二进制末尾到高位, 任意位置 u 包含 1 的个数 >= v 包含 1 的个数, 即可到达 v

    int main() {
        IOS;
        for (cin >> _; _; --_) {
            ll u, v; cin >> u >> v; bool f = 0;
            memset(a, 0, sizeof a); memset(b, 0, sizeof b);
    	if (u > v) f = 1;
            for (n = 0; u; a[++n] = (u & 1), u >>= 1);
            for (m = 0; v; b[++m] = (v & 1), v >>= 1);
    	    int sa = 0, sb = 0;
    	    rep (i, 1, m) {
                    sa += a[i]; sb += b[i];
    		if (sa < sb) f = 1;
            }
            cout << (!f ? "YES
    " : "NO
    ");
        }
        return 0;
    }
    

    E. Fib-tree

    二分 + dfs

    本质是个二分题, 每次将一棵树尝试分成两颗Fbi树 直到当前这棵树只有一个节点

    关键是怎么二分的问题, 二分一棵树, 就是找这棵树的一条边把这颗树分成两部分, 递归 判断这两棵子树是不是Fbi树

    然后就是怎么枚举边, 这个就很巧了, 通过dfs枚举当前这棵树的边, 本来dfs就是枚举边和点的, 一边枚举, 一边二分树

    注意到一棵树分成两棵Fbi树, 最多有两种分法 (fbi[i] = fbi[i - 1] + fbi[i - 2] = fbi[i - 2] * 2 + fbi[i - 3])

    即可找到两棵子孙, 其节点数量为fbi[i - 2]

    层数 * 当前子树的边数 * set维护断开了哪些边 即 期望为 (O(2^{logn} * logn * logn) = O(nlog^2n))

    int n, m, _, k, cas;
    int sz[50][N];
    bool st[N];
    set<pair<int, int>> v;
    VI h[N];
    
    bool work(int x, int fa, int sum, int d) {
        sz[d][x] = 1;
        if (!st[sum]) return 0;
        if (sum == 1) return 1;
        for (auto& y : h[x]) if (y != fa && !v.count({ min(x, y), max(x, y) })) {
            if (work(y, x, sum, d)) return 1;
            sz[d][x] += sz[d][y];
        }
        if (!st[sz[d][x]] || !st[sum - sz[d][x]]) return 0;
        v.insert({ min(x, fa), max(x, fa) });
        if (work(x, 0, sz[d][x], d + 1) && work(fa, 0, sum - sz[d][x], d + 1)) return 1;
        v.erase({ min(x, fa), max(x, fa) }); return 0;
    }
    
    int main() {
        IOS; cin >> n;
        for (int i = 0, j = 1; j <= n; st[j] = 1, swap(i += j, j));
        rep (i, 2, n) {
            int u, v; cin >> u >> v;
            h[u].pb(v); h[v].pb(u);
        }
        cout << (work(1, 0, n, 0) ? "YES" : "NO");
        return 0;
    }
    
  • 相关阅读:
    表达式和计算的描述
    表达式和计算的描述
    递归算法浅谈
    编程基本功训练:流程图画法及练习
    【2012.1.24更新】不要再在网上搜索eclipse的汉化包了!
    VS2008下直接安装使用Boost库1.46.1版本号
    android关键组件service服务(一)
    U盘安装咱中国人自己的操作系统UbuntuKylin14.04LST(超具体原创图文教程)
    数据流图的画法
    匈牙利算法
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/14464269.html
Copyright © 2011-2022 走看看