• Codeforces Round #343 (Div. 2)


     居然补完了

    组合 A - Far Relative’s Birthday Cake

    import java.util.*;
    import java.io.*;
    
    public class Main   {
        public static void main(String[] args)  {
            Scanner cin = new Scanner (new BufferedInputStream (System.in));
            int n = cin.nextInt ();
            int[] col = new int[105];
            String str;
            long ans = 0;
            for (int i=0; i<n; ++i) {
                str = cin.next ();
                int num = 0;
                for (int j=0; j<str.length (); ++j)  {
                    if (str.charAt (j) == 'C')  {
                        col[j]++;   num++;
                    }
                }
                ans += num * (num - 1) / 2;
            }
            for (int i=0; i<n; ++i) ans += col[i] * (col[i] - 1) / 2;
            System.out.println (ans);
        }
    }
    

    枚举 B - Far Relative’s Problem

    import java.util.*;
    import java.io.*;
    
    public class Main   {
        public static void main(String[] args)  {
            Scanner cin = new Scanner (new BufferedInputStream (System.in));
            int n = cin.nextInt ();
            String[] sex = new String[5005];
            int[] btime = new int[5005];
            int[] etime = new int[5005];
            for (int i=0; i<n; ++i) {
                sex[i] = cin.next ();
                btime[i] = cin.nextInt ();
                etime[i] = cin.nextInt ();            
            }
            int ans = 0;
            for (int i=1; i<=366; ++i)  {
                int male = 0, female = 0;
                for (int j=0; j<n; ++j) {
                    if (i >= btime[j] && i <= etime[j]) {
                        if (sex[j].charAt (0) == 'M')   male++;
                        else    female++;
                    }
                }
                if (male < female)  {
                    if (male * 2 > ans) ans = male * 2;
                }
                else    {
                    if (female * 2 > ans)   ans = female * 2;
                }
            }
            System.out.println (ans);
        }
    }
    

    DP C - Famil Door and Brackets

    题意:n长的字符串有‘(’和‘)’组成,现在已知其中m长的字串,问满足任意前缀字串‘(’数量不小于‘)’数量且最后两者数量相等的原字符串的方案数。

    分析:‘(’看作+1,‘(’看作-1。dp[i][j]表示前i个字符,和为j(j >= 0)的方案数,然后枚举m字符串前的字符个数p,那么m后q的个数也知道,根据总和为0可以得到前后组合,这里dp[n-m-i][j+now]用到对称思想。

    import java.util.*;
    import java.io.*;
    
    public class Main   {
        public static final int MOD = 1000000007;
        public static void main(String[] args)  {
            Scanner cin = new Scanner (new BufferedInputStream (System.in));
            Main ma = new Main ();
            int n = cin.nextInt ();
            int m = cin.nextInt ();
            char[] str = cin.next ().toCharArray ();
            long[][] dp = new long[2005][2005];
            dp[0][0] = 1;
            for (int i=1; i<=n-m; ++i)  {
                for (int j=0; j<=i; ++j)    {
                    if (j > 0)  {
                        dp[i][j] = ma.add (dp[i][j], dp[i-1][j-1]);
                    }
                    dp[i][j] = ma.add (dp[i][j], dp[i-1][j+1]);
                }
            }
            int mn = 10000000;
            int now = 0;
            for (int i=0; i<m; ++i)    {
                if (str[i] == '(')  now++;
                else    now--;
                if (now < mn)   mn = now;
            }
            long ans = 0;
            for (int i=0; i<=n-m; ++i)  {
                for (int j=0; j<=i; ++j)    {
                    if (j + mn >= 0 && j + now <= n - m - i)    {
                        ans = ma.add (ans, dp[i][j] * dp[n-m-i][j+now] % MOD);
                    }
                }
            }
            System.out.println (ans);
        }
        public long add(long a, long b)  {
            a += b;
            if (a >= MOD)   a -= MOD;
            return a;
        }
    }
    
    线段树+DP D - Babaei and Birthday Cake
    题意:求最大上升序列和
    分析:dp[i] 表示前i得到的最大上升序列和,dp[i] = dp[j] + vol[i] (vol[i] > vol[j])。用线段树优化动态统计前rk[i] - 1的最大值即dp[j],rk[i]是vol[i]离散化后的排名。
    #include <bits/stdc++.h>
    
    #define lson l, mid, o << 1
    #define rson mid + 1, r, o << 1 | 1
    const double PI = acos (-1.0);
    const int N = 1e5 + 5;
    struct Segment_Tree {
        double v[N<<2], mx[N<<2];
        void push_up(int o) {
            mx[o] = std::max (mx[o<<1], mx[o<<1|1]);
        }
        void build(int l, int r, int o) {
            if (l == r) {
                v[o] = mx[o] = 0;
                return ;
            }
            int mid = l + r >> 1;
            build (lson);   build (rson);
            push_up (o);
        }
        void updata(int p, double x, int l, int r, int o)   {
            if (l == r && l == p)   {
                v[o] = mx[o] = x;
                return ;
            }
            int mid = l + r >> 1;
            if (p <= mid)   updata (p, x, lson);
            else    updata (p, x, rson);
            push_up (o);
        }
        double query(int ql, int qr, int l, int r, int o)   {
            if (ql <= l && r <= qr) {
                return mx[o];
            }
            int mid = l + r >> 1;   double ret = 0;
            if (ql <= mid)  ret = std::max (ret, query (ql, qr, lson));
            if (qr > mid)   ret = std::max (ret, query (ql, qr, rson));
            return ret;
        }
    };
    double dp[N];
    int r[N], h[N];
    double vol[N], V[N];
    
    int main(void)  {
        int n;  scanf ("%d", &n);
        for (int i=0; i<n; ++i) {
            scanf ("%d%d", r + i, h + i);
            vol[i] = PI * r[i] * r[i] * h[i];
            V[i] = vol[i];
        }
        std::sort (V, V+n);
        Segment_Tree st;
        st.build (1, n, 1);
        for (int i=0; i<n; ++i) {
            int pos = std::lower_bound (V, V+n, vol[i]) - V + 1;
            if (pos == 1)   dp[i] = vol[i];
            else    dp[i] = st.query (1, pos - 1, 1, n, 1) + vol[i];
            st.updata (pos, dp[i], 1, n, 1);
        }
        double ans = 0;
        for (int i=0; i<n; ++i) {
            if (ans < dp[i])    ans = dp[i];
        }
        printf ("%.10f
    ", ans);
    
        return 0;
    }
    

    LCA + DP + DFS E - Famil Door and Roads

    题意:加一条边,使形成简单环(无重边),u和v在其中的方案数

    分析:加一条边一定是从u或v引出一条边到w而且w能到另一个点。无重边就是w不能选择u到v路径上的点。

      dep[u]:根节点1到u的距离   sz[u]:u的子树包括u的结点数  sdown[u]:在u的子树下到u的距离和,树形dp

      sall[u]:所有点到u的距离和,由sdown[u]得到,也是树形DP

      一共有3种情况:1.LCA (u, v) == v,除v子树外所有点到v的距离和/点数 + u子树所有点到u的距离 / 点数

              2.LCA (v, u) == u,同1

              3.除1,2的情况,只能在u或v的子树选择一节点才能构成环,u子树所有点到u的距离 / 点数 + v子树所有点到v的距离 / 点数

      最后还要加上不变的距离 dis (u, v) + 1。学习大牛的代码,获益匪浅

    #include <bits/stdc++.h>
    
    const int N = 1e5 + 5;
    const int D = 20;
    std::vector<int> G[N];
    int dep[N], sz[N];
    long long sdown[N], sall[N];
    int rt[N][D];
    int n, m;
    
    void DFS(int u, int fa) {       //get rt[v][0], sdown[u] and dep[v]
        sdown[u] = 0;   sz[u] = 1;
        for (int i=0; i<G[u].size (); ++i)  {
            int v = G[u][i];
            if (v == fa || dep[v] != 0)    continue;
            rt[v][0] = u;
            dep[v] = dep[u] + 1;
            DFS (v, u);
            sdown[u] += sdown[v] + sz[v];
            sz[u] += sz[v];
        }
    }
    
    void DFS2(int u, int fa)    {       //get sall[v]
        for (int i=0; i<G[u].size (); ++i)  {
            int v = G[u][i];
            if (v == fa)    continue;
            sall[v] = sall[u] + n - 2 * sz[v];
            DFS2 (v, u);
        }
    }
    
    void init_LCA(void) {
        for (int i=1; i<D; ++i) {
            for (int j=1; j<=n; ++j)    {
                rt[j][i] = rt[j][i-1] == 0 ? 0 : rt[rt[j][i-1]][i-1];
            }
        }
    }
    
    int up(int u, int d)    {
        for (int i=D-1; i>=0; --i)  {
            if (d < (1 << i))   continue;
            u = rt[u][i];   d -= (1 << i);
        }
        return u;
    }
    
    int LCA(int u, int v)   {
        if (dep[u] < dep[v])    std::swap (u, v);
        for (int i=0; i<D; ++i) {
            if ((dep[u] - dep[v]) >> i & 1) {
                u = rt[u][i];
            }
        }
        if (u == v) return u;
        for (int i=D-1; i>=0; --i)  {
            if (rt[u][i] != rt[v][i])   {
                u = rt[u][i];
                v = rt[v][i];
            }
        }
        return rt[u][0];
    }
    
    int main(void)  {
        scanf ("%d%d", &n, &m);
        for (int u, v, i=0; i<n-1; ++i) {
            scanf ("%d%d", &u, &v);
            G[u].push_back (v);
            G[v].push_back (u);
        }
        dep[1] = 0;
        DFS (1, 0);
        sall[1] = sdown[1];
        DFS2 (1, 0);
        init_LCA ();
        while (m--) {
            int u, v;   scanf ("%d%d", &u, &v);
            int lca = LCA (u, v);
            double ans = dep[u] + dep[v] - 2 * dep[lca] + 1;
            if (lca == v || lca == u)   {
                if (lca == u)   std::swap (u, v);
                int v2 = up (u, dep[u] - dep[v] - 1);
                long long supv = sall[v] - sdown[v2] - sz[v2];
                ans += 1.0 * supv / (n - sz[v2]) + 1.0 * sdown[u] / sz[u];
            }
            else    {
                ans += 1.0 * sdown[u] / sz[u] + 1.0 * sdown[v] / sz[v];
            }
            printf ("%.12f
    ", ans);
        }
    
        return 0;
    }
    

      

    编译人生,运行世界!
  • 相关阅读:
    VUE的生命周期
    ID生成算法(二)
    ID生成算法(一)——雪花算法
    HTTP状态码和支持的方法
    水平居中/垂直居中/水平垂直居中总结
    判断数组类型的4种方法
    WebSocket浅谈
    vue中使用定时器时this指向
    银行转账业务梳理
    支付那些事儿
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5209601.html
Copyright © 2020-2023  润新知