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;
}