Educational Codeforces Round 91 (Rated for Div. 2) (C、D)

C. Create The Teams - 贪心

题意 :
(多组输入)
将n个人分组
每组要满足 : 组员数 * 组内最小能力值 >= x
问题 :
求最多分成几组

思路 :
先对n个人以能力值排序,再从大到小取出。
若 累计组员数 * 目前取出值 >= x,则分为一组
(保证让尽可能少的人分为一组)

AC代码 :

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <iomanip>
#define ll long long
#define INF 1000000010
const int MAX = 2e5 + 10;
using namespace std;
ll a[MAX];
int main()
{
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    int t, n, x;
    cin >> t;
    while (t--)
    {
        int cnt = 0;
        cin >> n >> x;
        for (int i = 0; i < n; i++)
            cin >> a[i];
        sort(a, a + n);
        ll sum = 1;	//注意数据范围可能爆int
        for (int i = n - 1; i >= 0; i--)
        {
            if (a[i] * sum >= x)
            {
                cnt++;
                sum = 1;
            }
            else
                sum++;
        }
        cout << cnt << endl;
    }
    return 0;
}

D. Berserk And Fireball - 模拟

题意 :
将 原数组 通过两个方式 变为 目标数组(原数组的元素为1到n不重复元素)
方式1 : 花费 x,准确的将k个连续元素移出数组 (必须为k个)
方式2 : 花费 y,选中两个连续元素 将数值小的元素移出数组
问题 :
求变为目标数组的最小花费

思路 :
1、分情况讨论
若 x < k*y,则 方式1更划算 (尽可能的多用方式1)
反之,则 方式2更划算 (尽可能的多用方式2)
2、分组处理
每个目标元素都不能被移出,因此两个目标元素间(这里包括开头和结尾的元素),分为一组处理
3、细节
方式1: 必须在长度大于等于k才能使用
方式2 :
长度小于k时,要考虑组内元素最大值是否小于左右的目标元素
若小于将无法移出组内这个元素
长度大于等于k时,若组内元素最大值不小于左右的目标元素,可以先用方式2移出其他元素,留下无法移出的元素用方式1移出

AC代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <iomanip>
#define ll long long
#define INF 1000000010
const int MAX = 2e5 + 10;
using namespace std;
int a[MAX], b[MAX], vis[MAX], mx[MAX];
int main()
{
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    int t, n, m;
    ll x, k, y;
    cin >> n >> m >> x >> k >> y;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < m; i++)
        cin >> b[i];
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        if (a[i] == b[ans])
        {
            vis[ans] = i;
            ans++;
        }
        if (ans == m)
            break;
    }
    if (ans != m)
    {
        cout << -1 << endl;
        return 0;
    }
    vis[m] = n;
    ll cnt = 0; //注意数据范围可能爆int
    int st = -1;
    if (y * k >= x)
    {
        for (int i = 0; i <= m; i++)
        {
            int mx = 0;
            for (int j = st + 1; j < vis[i]; j++)
                mx = max(mx, a[j]);
            int len = vis[i] - st - 1;
            if (len < k && (st == -1 || mx > a[st]) && mx > a[vis[i]])
            {
                cout << -1 << endl;
                return 0;
            }
            cnt += (len / k) * x + (len % k) * y;
            st = vis[i];
        }
    }
    else
    {
        for (int i = 0; i <= m; i++)
        {
            int mx = 0;
            for (int j = st + 1; j < vis[i]; j++)
                mx = max(mx, a[j]);
            int len = vis[i] - st - 1;
            if (len < k && (st == -1 || mx > a[st]) && mx > a[vis[i]])
            {
                cout << -1 << endl;
                return 0;
            }
            else if (mx > a[st] && mx > a[vis[i]])
                cnt += x + (len - k) * y;
            else
                cnt += len * y;
            st = vis[i];
        }
    }
    cout << cnt << endl;
 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值