• Codeforces Round #219 (Div. 2) 题解


    A.Collecting Beats is Fun

    题意:有4*4的矩阵,矩阵上有0-9的数字,3表示在第3秒的时候要按他,一只手一秒最多按k个,问能不能把规定的都按完

    思路:直接模拟

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    map<int, int> mp;
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= 4; i++) {
            for(int j = 1; j <= 4; j++) {
                char ch;
                cin>>ch;
                if('0' <= ch && ch <= '9')
                    mp[ch - '0']++;
            }
        }
        bool ok=true;
        for(int i = 0; i <= 9; i++) {
            if(mp[i] > 2 * n) {
                ok =false; break;
            }
        }
        if(ok) puts("YES");
        else puts("NO");
        return 0;
    }
    View Code

    B.Making Sequences is Fun

    题意:s(n)表示n的位数,现在有w元,向数列中加入数x,要花费s(x)*k元现在数列中的第一个数是m,构造一个m,m+1,m+2…这样的数列,最长为多长

    思路:先求出数列的长度,然后看与上一个10的次方还差多少,如果可以整除的话直接跳上去,一直到不能减为止

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    int getlen(LL x)
    {
        int res = 0;
        while(x) {
            x /= 10;
            res ++;
        }
        return res;
    }
    int main()
    {
        LL w, m, k;
        scanf("%lld%lld%lld", &w, &m, &k);
        w /= k;
        int len = getlen(m);
    //    printf("test %d
    ",len);
        LL num = 1;
        for(int i = 1; i <= len; i++)
            num *= 10;
        LL ans = 0;
        for(int i = len; ; i++) {
            if(w - (num - m) * i >= 0) {
                w -= i * (num - m);
                ans += num - m;
                m = num;
                num *= 10;
            }
            else {
                ans += w / i;
                break;
            }
        }
        cout<< ans <<endl;
        return 0;
    }
    View Code

    C. Counting Kangaroos is Fun

        题意:有n(5e5)只袋鼠,每只袋鼠都有一个体重,每只袋鼠中的口袋可以装比它体重小于等于一半的袋鼠,只能装一只,被装进去的袋鼠不能装东西,装到口袋中的袋鼠不会被看到,问最少能看到几只袋鼠;

        思路:因为最多装n/2只袋鼠,所以设置两个指针i=1,j=n/2,一只遍历,能装几个装几个

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=5e5+7;
    int a[maxn];
    int n;
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        int ans=0;
        for(int i=1,j=n/2+1;i<=n/2&&j<=n;){
            if(a[i]*2<=a[j]){
                ans++;i++;j++;
            }
            else j++;
        }
        printf("%d
    ",n-ans);
        return 0;
    }
    View Code

    D. Counting Rectangles is Fun

        题意:有一个n*m(40)的01矩阵,有q次询问,每次询问矩形(a,b)(c,d)中有多少个全0的矩形

        思路:定义dp[i][j][p][q]为(i,j)到(p,q)中全0矩形的个数,维护一个数组num[i][j]表示,在[i][j]位置的数字左侧有多少个连续的0,在转移的时候需要先容斥一下,然后只需要计算包含右下角的0矩形个数,从下向上扫一下,加上即可以了

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int dp[45][45][45][45];
    int a[45][45];
    int num[45][45];
    int n,m,Q;
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&Q);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%1d",&a[i][j]);
                num[i][j]=num[i][j-1];
                if(a[i][j])num[i][j]=0;
                else num[i][j]++;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                for(int p=i;p<=n;p++){
                    for(int q=j;q<=m;q++){
                        dp[i][j][p][q]=dp[i][j][p-1][q]+dp[i][j][p][q-1]-dp[i][j][p-1][q-1];
                        int res=q-j+1;
                        for(int as=p;as>=i;as--){
                            res=min(res,num[as][q]);
                            dp[i][j][p][q]+=res;
                        }
                    }
                }
            }
        }
        while(Q--){
            int b,c,d,e;
            scanf("%d%d%d%d",&b,&c,&d,&e);
            printf("%d
    ",dp[b][c][d][e]);
        }
        return 0;
    }
    View Code

    E. Watching Fireworks is Fun

        题意:在一个长度为n(150000)的数轴上,有m(300)个烟花,每个烟花在ai的位置上,在ti秒放,假设站在x的位置上可以获得bi-abs(ai-x)的幸福值,每秒人移动的距离是d,人最开始可以在任何一个位置,每个烟花都要看,问最多获得多少幸福值。

        思路:定义dp[i][j]表示前i个烟花放了以后,站在第j个位置可以获得的最大幸福值,那么dp[i][j]=max(dp[i-1][j+k*d]+b[i]-abs(a[i]-j));可以用一个单调队列维护来进行优化,如果新来的比队尾大,就可以弹出队尾,维护一个递减的单调队列,当前最优的一直在队首。

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int maxn = 150000 + 7;
    int n,m;
    LL d;
    LL dp[2][maxn];
    LL a[305],b[305],t[305];
    LL que[maxn];
    int main()
    {
        scanf("%d%d%lld", &n, &m, &d);
        for(int i = 1; i <= m; i++) {
            scanf("%lld%lld%lld", &a[i], &b[i], &t[i]);
        }
        int now=0;
        LL pre = t[1];
        for(int i = 1; i <= m; i++) {
            int k = 1;
            if(pre == t[i]) {
                for(int j = 1; j <= n; j++) {
                    dp[now][j] = dp[now^1][j] + b[i] - abs(a[i] - j);
                }
            }
            else {
                int L = 1, R = 0;
                LL len = d * (t[i] - pre);
                pre = t[i];
                for(int j = 1; j <= n; j++) {
                    while(k <= n && k <= j + len) {
                        while(L <= R && dp[now ^ 1][que[R]] < dp[now ^ 1][k]) R--;
                        que[++ R] = k ++;
                    }
                    while(L <= R && j - len > que[L]) L++;
                    dp[now][j] = dp[now ^ 1][que[L]] + b[i] - abs(a[i] - j);
                }
            }
            now ^= 1;
        }
        LL ans = -1e18;
        for(int i = 1; i <= n ;i ++) {
            ans = max(ans, dp[now ^ 1][i]);
        }
        cout<< ans <<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    什么是多线程中的上下文切换?
    什么是基本表?什么是视图?
    什么是存储过程?用什么来调用?
    随意写文件命令?怎么向屏幕输出带空格的字符串,比如” hello world”?
    NULL 是什么意思 ?
    Mock 或 Stub 有什么区别?
    什么叫视图?游标是什么?
    什么是微服务中的反应性扩展?
    什么是线程组,为什么在 Java 中不推荐使用?
    Java 中用到的线程调度算法是什么?
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/10383482.html
Copyright © 2020-2023  润新知