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\n",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",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\n",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

 

转载于:https://www.cnblogs.com/lalalatianlalu/p/10383482.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值