zoukankan      html  css  js  c++  java
  • [CodeForces]Educational Codeforces Round 28

    846A. Curriculum Vitae

    题意

    给定一个长度为$n$的$01$序列,删掉一些数,使得最终数列中$0$不直接跟在$1$后面,求最长长度。

    题解

    最终序列一定是$000...111$形式的,$Theta(n)$枚举最后一个$0$的位置,用前缀和$Theta(1)$统计一下即可。
    时间复杂度:$Theta(n)$。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 109;
    int s[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline int count(int l, int r) {
        return (r >= l ? s[r] - s[l - 1] : 0);
    }
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) s[i] = read() + s[i - 1];
        int res = 0;
        for (int i = 0; i <= n; i++) res = max(res, i - count(1, i) + count(i + 1, n));
        return 0 * printf("%d
    ", res);
    }
    

    846B. Math Show

    题意

    给定$n$个大题,每个大题都有$k$个小题,第$i$个小题需要花费$t_i$分钟。每做出一小题得$1$分,每做出完整的一个大题多得一分,即$k+1$分。求在$M$分钟完成的最大得分。

    题解

    先枚举完整做出的大题数,再按每小题花费时间的贪心即可。
    时间复杂度:$Theta(n^2 imes k)$。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 59;
    int t[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    int main() {
        int n = read(), k = read(), m = read(), s = 0;
        for (int i = 1; i <= k; i++) t[i] = read(), s += t[i];
        sort(t + 1, t + k + 1);
        ll res = 0;
        for (int i = 0; i <= n; i++) {
            ll tim = i * s, cur = i * (k + 1);
            if (tim > m) break;
            for (int j = 1; j <= k; j++) {
                if (tim + (n - i) * t[j] <= m) tim += (n - i) * t[j], cur += (n - i);
                else {
                    while (tim + t[j] <= m) tim += t[j], cur++;
                    break;
                }
            }
            res = max(res, cur);
        }
        return 0 * printf("%d
    ", res);
    }
    

    846C. Four Segments

    题意

    给定长度为$n$的数列$a_0,a_1,...,a_{n-1}$,定义$sum(l,r)$为区间$[l,r)$内$a_i$的和。求三个数$delim_0,delim_1,delim_2(0leq delim_0leq delim_1leq delim_2
    leq n)$将数列分成四段,使得$res=sum(0,delim_0)-sum(delim_0,delim_1)+sum(delim_1,delim_2)-sum(delim_2,n)$最大。

    题解

    考虑先枚举$delim_1$定下来,再在区间$[0,delim_1]$和$[delim_1,n]$中分别枚举$delim_0$和$delim_2$,这时只要让$sum(0,d_0)$和$sum(d1,d2)$同时取最大,用前缀和加速即可。
    时间复杂度:$Theta(n^2)$。

    代码

    #include <bits/stdc++.h>
    #define DE(x) cout << x << endl
    using namespace std;
    typedef long long ll;
    const int N = 5009;
    int a[N];
    ll s[N];
    struct Sol {
        int d0, d1, d2;
        ll res;
    };
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline ll sum(int l, int r) {
        if (l < 0) return s[r - 1];
        return l <= r ? s[r - 1] - s[l - 1] : 0;
    }
    int main() {
        int n = read();
        for (int i = 0; i < n; i++) a[i] = read();
        s[0] = a[0];
        for (int i = 1; i < n; i++) s[i] = s[i - 1] + a[i];
        Sol ans; ans.d0 = ans.d1 = ans.d2 = ans.res = 0;
        for (int d1 = 0; d1 <= n; d1++) {
            int d0 = d1, d2 = d1;
            for (int j = 0; j <= d1; j++) if (sum(0, j) > sum(0, d0)) d0 = j;
            for (int j = d1; j <= n; j++) if (sum(d1, j) > sum(d1, d2)) d2 = j;
            ll res = sum(0, d0) - sum(d0, d1) + sum(d1, d2) - sum(d2, n);
            if (res > ans.res) ans.res = res, ans.d0 = d0, ans.d1 = d1, ans.d2 = d2;
        }
        return 0 * printf("%d %d %d
    ", ans.d0, ans.d1, ans.d2);
    }
    

    846D. Monitor

    题意

    给定一$n imes m$个的点阵,其中有$q$个点$(x_i,y_i)$会在$t_i$时刻变成坏点。求最少何时,存在一个$k imes k$的点阵全是坏点。

    题解

    二分时间,单调性显然,用二维前缀和判断是否全是坏点即可。
    时间复杂度:$Theta(n^2 imes log q)$。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 509;
    int n, m, k, q, x[N*N], y[N*N], t[N*N], s[N][N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline bool broke(int mid) {
        memset(s, 0, sizeof(s));
        for (int i = 1; i <= q; i++) if (t[i] <= mid) s[ x[i] ][ y[i] ] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
            }
        }
        for (int i = k; i <= n; i++) {
            for (int j = k; j <= m; j++) {
                if (s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k] == k * k) return true;
            }
        }
        return false;
    }
    int main() {
        n = read(), m = read(), k = read(), q = read();
        for (int i = 1; i <= q; i++) x[i] = read(), y[i] = read(), t[i] = read(), t[0] = max(t[0], t[i]);
        int l = -1, r = t[0] + 1, res = -1;
        while (l + 1 < r) {
            int mid = (l + r) >> 1;
            if (broke(mid)) r = mid, res = r; else l = mid;
        }
        return 0 * printf("%d
    ", res);
    }
    

    846E. Chemistry in Berland

    题意

    给定$n$个物品,现各有$b_i$千克,各需要$a_i$千克。其中$k_i$千克的$x_i$物品可以转化成$1$千克的$i$物品,$1$千克的$i$物品可以转化成$1$千克的$x_i$物品。判断能否通过转化使得$n$种物品都满足需求。

    题解

    树形$DP$。按着题目所述转化条件转移状态即可。注意数据范围。
    时间复杂度:$Theta(n)$。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, ll> pll;
    const int N = 1e5+9;
    ll sum, a[N], b[N], x[N], k[N];
    vector<pll> g[N];
    bool flag = 1;
    inline ll read() {
        ll s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline void dfs(int u) {
        for (auto e : g[u]) {
            int k = e.first, v = e.second;
            dfs(v);
            if (b[v] > 0) b[u] += b[v];
            else {
                double w = 1.0 * b[v] * k;
                if (b[u] + w < -sum) flag = 0;
                b[u] += b[v] * k;
            }
        }
    }
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) b[i] = read(), sum += b[i];
        for (int i = 1; i <= n; i++) a[i] = read(), b[i] -= a[i];
        for (int i = 2; i <= n; i++) {
            int x = read(), k = read();
            g[x].push_back(make_pair(k, i));
        }
        dfs(1);
        return 0 * puts(b[1] >= 0 ? "YES" : "NO");
    }
    

    846F. Random Query

    题意

    给定$n$个正整数$a_i$,每次随机地选择两个数$l,r$(若$l>r$,则交换两者),定义$(l,r)$的$value$为$a_l,a_{l+1},...,a_r$中不同的数的个数。求$value$的期望。

    题解

    我们考虑计算$a_l,a_{l+1},...,a_r$中每个数第一次出现的位置。记$pre[i]$表示$i$之前与$a_i$相等的最近的一个数的位置,则$a_i$能对所有$lin (pre[i],i],rin [i,n]$的所有区间产生$1$个贡献。
    故所求期望为$res=frac{2*sum_{i=1}{n}{(i-pre[i])(n-i+1)}-n}{n2}$。
    时间复杂度:$Theta(n)$。

    代码

    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e6+9;
    int a[N], pos[N], pre[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) a[i] = read(), pre[i] = pos[ a[i] ], pos[ a[i] ] = i;
        ll res = 0;
        for (int i = 1; i <= n; i++) res += 1ll * (i - pre[i]) * (n - i + 1);
        res = res * 2 - n;
        return 0 * printf("%.6lf
    ", 1.0 *  res / (1ll * n * n));
    }
    
  • 相关阅读:
    音标,口型,舌位对照表:适合已有一定英语基础的人重新回顾音标发音,在不断的练习中让自己的发音更准确,口型更标准。
    c++友元函数和友元类
    经典MFC界面和Ribbon界面框架对比(单文档为例)
    QEM三维模型简化算法
    VC6和VS2008中C++编译器差异
    VS操作技巧
    msvcrt.lib和LIBCD.lib链接冲突
    二叉树遍历算法
    IE/QQ使用代理上网
    Google Map街景(红蓝立体)
  • 原文地址:https://www.cnblogs.com/jstztzy/p/7496021.html
Copyright © 2011-2022 走看看