zoukankan      html  css  js  c++  java
  • Codeforces Round #627 (Div. 3)

    D. Pair of Topics

    题目:https://codeforces.com/contest/1324/problem/D

    题解

    将不等式变下形:(a_i + a_j > b_i + b_j)等价于(a_i - b_i > b_j - a_j)
    (c[i] = a_i - b_i, d[j] = b[j] - a[j]),问题转化为对于每一个(c),有多少个(d)小于它。将(d)排序,然后二分查找即可。

    注意去重(a[i] > b[i])的情况

    int main() {
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
        }
    
        long long ans = 0;
        for (int i = 1; i <= n; ++i) {
            cin >> b[i];
            c[i] = a[i] - b[i];
            if (c[i] > 0) ans--;
            b[i] = b[i] - a[i];
    
        }
    
        sort(b + 1, b + n + 1);
    
        for (int i = 1; i <= n; ++i) {
            ans += lower_bound(b + 1, b + n + 1, c[i]) - (b + 1);
        }
        cout << ans / 2 << endl;
        return 0;
    }
    

    E. Sleeping Schedule

    题目:https://codeforces.com/contest/1324/problem/E
    决定多练练DP,orz

    题解

    对于每次碎觉,可以选择提前睡或者不提前睡
    (dp[i][j]:=) 睡觉次数为(i),提前睡了(j)次的 (good) (sleeping) (times) (很自然的定义,有木有),(sum[i] = sum_{j = 1}^{i}a_i),有:

    • (dp[i][j]) = (max(dp[i - 1][j]), (dp[i - 1][j - 1]) + check((sum - j) \% h, l, r))

    注意边界!

    只需要知道提前睡了几次,不用记录是哪几次提前睡的(%%%出题人)。因为模运算可以合并

    /*cf给出代码一向都很nice,用vector初始化二维数组是真的方便*/
    
    inline bool check(int x, int l, int r) {
        return (l <= x && x <= r);
    }
    
    void Solve() {
        int n, h, l, r;
        cin >> n >> h >> l >> r;
    
        vector<int> a(n + 1);
        for (int i = 1; i <= n; ++i) cin >> a[i];
    
        vector<vector<int> > dp(n + 1, vector<int>(n + 1, -INF));
        dp[0][0] = 0;
    
        int sum = 0;
        for (int i = 1; i <= n; ++i) {
            sum += a[i];
            dp[i][0] = dp[i - 1][0] + check(sum % h, l, r);
            for (int j = 1; j < i; ++j) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + check((sum - j) % h, l, r);
            dp[i][i] = dp[i - 1][i - 1] + check((sum - i) % h, l, r);
        }
    
        cout << *max_element(dp[n].begin(), dp[n].end()) << endl;
    }
    
    

    F. Maximum White Subtree

    一棵树(无根)有(n)个节点,每个节点都被染色(黑色 or 白色)
    对于每个节点,找一个包含该节点的连通块,使得连通块中白色节点的个数与黑色节点个数的差值最大,既(Cnt_{white} -Cnt_{black})最大

    题解

    题目中(subtree)指的是包含节点(u)的连通块。
    假如这是一颗有根树,对于每个节点,只考虑求: 以该节点为根的子树的(max(Cnt_w - cnt_b))。那么自底向上(dp)统计即可:
    (dp[u]:=cnt_w - cnt_b),则(dp[parent_u] = dp[parent_u] + (dp[u] > 0 ? dp[u] : 0))
    显然,这样只正确求出了根节点的答案。对于除根以外的节点,都没有考虑(parent_u)对节点(u)的贡献。
    (ans[u]:=)节点(u)的完整答案,则(ans[root] =dp[root])。假设我们已经求得了(ans[parent_u]),怎么求(ans[u])呢?仔细观察一下,发现:

    1. (dp[u] leq 0),意味着(u)(parent_u)没有贡献
      • (ans[parent_u] leq 0),则 (ans[u] = dp[u])
      • (ans[parent_u] > 0),则 (ans[u] = ans[parent_u] + dp[u])
    2. (dp[u] > 0)
      • (ans[parent_u] leq dp[u]),则 (ans[u] = dp[u])
      • (ans[parent_u] > 0),则 (ans[u] = ans[parent_u])

    整理一下,然后(code)

    
    int n, cnt;
    int dp[MAXN], ans[MAXN], head[MAXN];
    
    struct edge { int to, next; } e[MAXN * 2];
    
    void Inite() {
        cnt = 0;
        memset(head, -1, sizeof(head));
    }
    
    void add_edge(int u, int v) {
        e[cnt].to = v;
        e[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    void DFS_down_to_top(int u, int p) {
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (p == v) continue;
            DFS_down_to_top(v, u);
            dp[u] += (dp[v] > 0 ? dp[v] : 0);
        }
    }
    
    void DFS_top_to_down(int u, int p) {
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (p == v) continue;
            if (dp[v] <= 0) {
                if (ans[u] <= 0) ans[v] = dp[v];
                else ans[v] = dp[v] + ans[u];
            }
            else {
                if (ans[u] <= dp[v]) ans[v] = dp[v];
                else ans[v] = ans[u];
            }
            DFS_top_to_down(v, u);
        }
    }
    
    int main() {
    
        Inite();
    
        cin >> n;
        for (int i = 1, u; i <= n; ++i) {
            cin >> u;
            dp[i] = (u == 1 ? 1 : -1);
        }
       
        for (int i = 1, u, v; i < n; ++i) {
            cin >> u >> v;
            add_edge(u, v);
            add_edge(v, u);
        }
    
        DFS_down_to_top(1, -1);
        ans[1] = dp[1];
        DFS_top_to_down(1, -1);
    
        for (int i = 1; i <= n; ++i) cout << ans[i] << " ";
        cout << endl;
    
        return 0;
    }
    
    
    
  • 相关阅读:
    杭电2048--神、上帝以及老天爷
    杭电1012--u Calculate e
    杭电2049--不容易系列之(4)——考新郎
    杭电2045--不容易系列之(3)—— LELE的RPG难题
    Truncate Table user
    Sql server统计查询语句消耗时间
    C/C++:Unions 联合
    NYOJ 27 水池数目
    OpenRisc-39-ORPSoC,or1200的memory hierarchy整体分析
    RCP打包出来 运行 出现 JVM terminated.exit code = 13
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/12582941.html
Copyright © 2011-2022 走看看