Schwertlilien
As a recoder: notes and ideas.

2023.3.26

2023.3.26

[TOC]

P4995 跳跳

你是一只小跳蛙,你特别擅长在各种地方跳来跳去。

这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 $i$ 块的石头高度为 $h_i$,地面的高度是 $h_0 = 0$。你估计着,从第 $i$ 块石头跳到第 $j$ 块石头上耗费的体力值为 $(h_i - h_j) ^ 2$,从地面跳到第 $i$ 块石头耗费的体力值是 $(h_i) ^ 2$。

为了给小 F 展现你超级跳的本领,你决定跳到每个石头上各一次,并最终停在任意一块石头上,并且小跳蛙想耗费尽可能多的体力值。

当然,你只是一只小跳蛙,你只会跳,不知道怎么跳才能让本领更充分地展现。

不过你有救啦!小 F 给你递来了一个写着 AK 的电脑,你可以使用计算机程序帮你解决这个问题,万能的计算机会告诉你怎么跳。

那就请你——会写代码的小跳蛙——写下这个程序,为你 NOIp AK 踏出坚实的一步吧!

这个题要求从地面上跳到一块石头上,然后再在不同的石头上跳来跳去,使得消耗的体力最大。

需要注意的是:只能由地面跳到石头上一次,然后不能先挑到地面上然后再跳到石头上。

然后我们跳的思路就是:先从地面上跳到最高的石头,再跳到最低的石头;再跳到次高的石头···

Main goal:使得每两次跳跃的石头的高度差max

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>
using namespace std;

int n;
long long ans;
vector <int> a;

inline int max(vector<int> &a) {
auto now_pos = max_element(a.begin(), a.end());
int now_index = now_pos - a.begin();
//cout << "max:" << now_index << endl;
return now_index;
}

inline int min(vector<int> &a) {
auto now_pos = min_element(a.begin(), a.end());
int now_index = now_pos - a.begin();
//cout << "min:" << now_index << endl;
return now_index;
}


int main() {
bool flag = false;
//false:max-min(last)
//true:min-max(last)
int last = 0, index, num;

cin >> n;
for (int i = 1; i <= n; i++) {
cin >> num;
a.push_back(num);
}

while (!a.empty()) {
if (!flag) { //取max
flag = true;
index = max(a);
ans += (a[index] - last) * (a[index] - last);
} else {
flag = false;
index = min(a);
ans += (last - a[index]) * (last - a[index]);
}
last = a[index];
a.erase(a.begin() + index);
}
cout << ans;
}

P1090合并果子

在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 $n-1$ 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 $1$ ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有 $3$ 种果子,数目依次为 $1$ , $2$ , $9$ 。可以先将 $1$ 、 $2$ 堆合并,新堆数目为 $3$ ,耗费体力为 $3$ 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 $12$ ,耗费体力为 $12$ 。所以多多总共耗费体力 $=3+12=15$ 。可以证明 $15$ 为最小的体力耗费值。

和上面这个题差不多捏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;

int n, num, sum = 0;
vector<int> a;

int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num;
a.push_back(num);
}

while (a.size() > 1) {
sort(a.begin(), a.end());
int cost = a[0] + a[1];
sum += cost;
a.erase(a.begin(), a.begin() + 2);
a.push_back(cost);
}
cout << sum;
}

结果这么写T了,只有30分。改用优先队列,省去每次循环都要排序,然后过了。

ps: 这里不是说优先队列就不用排序,只是在push的时候根据小根堆的结点来插入,会更快)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h>
using namespace std;

int n, num, sum = 0;
priority_queue<int, vector<int>, greater<int>>q;

int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num;
q.push(num);
}

while (q.size() > 1) {
int cost = q.top();
q.pop();
cost += q.top();
q.pop();
q.push(cost);

sum += cost;
}
cout << sum;
}

P4447分组–受挫

小可可的学校信息组总共有 $n$ 个队员,每个人都有一个实力值 $a_i$。现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的 $n$ 个队员分成若干个小组去参加这场比赛。

但是每个队员都不会愿意与实力跟自己过于悬殊的队员组队,于是要求分成的每个小组的队员实力值连续,同时,一个队不需要两个实力相同的选手。举个例子:$[1, 2, 3, 4, 5]$ 是合法的分组方案,因为实力值连续;$[1, 2, 3, 5]$ 不是合法的分组方案,因为实力值不连续;$[0, 1, 1, 2]$ 同样不是合法的分组方案,因为出现了两个实力值为 $1$ 的选手。

如果有小组内人数太少,就会因为时间不够而无法获得高分,于是小可可想让你给出一个合法的分组方案,满足所有人都恰好分到一个小组,使得人数最少的组人数最多,输出人数最少的组人数的最大值。

注意:实力值可能是负数,分组的数量没有限制。

噢我的上帝啊,瞧瞧“使得人数最少的组人数最多,输出人数最少的组人数的最大值”这句话多么拗口啊。

但是这句话也是一个典型的二分答案。

当我们看到最大值最小化,最小值最大化,以及一些连续性限制时,通常会想到使用二分答案来解决问题。具体来说,我们可以二分一个小组的人数,然后检查能否将所有队员分成若干个小组,满足每个小组的人数不超过二分得到的值,并且每个小组的队员实力值连续,且没有出现相同实力值的队员。

由于要检查每个小组的队员实力值是否连续,我们需要将队员按照实力值排序。排序之后,我们可以使用一个二维数组 groups 来保存已经分好的小组,其中 groups[i] 表示第 $i$ 个小组中的队员实力值,从小到大排序。

我们从左到右扫描排序后的队员实力值。如果遇到相同实力值的队员,就无法满足条件,因为一个小组中不能有两个实力值相同的队员。如果当前队员实力值和上一个小组的最大实力值连续,那么我们将其添加到上一个小组中,否则我们新开一个小组。

在检查能否将所有队员分成若干个小组时,我们从前往后遍历小组,对于每个小组,我们需要检查:

  1. 最小值是否小于当前二分得到的值减一,如果是,那么这个小组无法满足条件;
  2. 当前组的人数是否超过二分得到的值,如果是,那么这个小组无法满足条件;
  3. 最大值是否大于下一个小组的最小值加上当前二分得到的值减一,如果是,那么这个小组无法满足条件。

如果所有小组都能满足条件,那么当前二分得到的值就是最小的满足条件的小组人数,否则我们需要增大小组人数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int n,num;
vector<int> vec;

int main() {

cin>>n;
for(int i=1;i<=n;i++){
cin>>num;
vec.push_back(num);
}
sort(vec.begin(),vec.end());

return 0;
}

NovelNook

goal: online library management system

The British Library

provide info services to academic,business,research and scientific communities.

  • access the catalog
  • manage usr accounts
  • borrow materials
  • 它还应该通过自动发送过期提醒和处理新材料等任务来简化图书馆的操作。

Catalog

  • books
  • ebooks
  • DVDs
  • CDs

可以according to 标题、作者、主题和其他相关标准搜索

Usr manage

登录系统,允许用户:、

  • 创建账户
  • 查询借阅历史
  • 保存借出的items

system

  • auto 追踪checkout dates/due dates
  • send reminders
  • assess late fees
  • manage 每本书的 multiple copies –track their stats(location,availbility)
  • 处理新的materials

USR

reader

他们借阅资料并使用图书馆的资源。他们可以登录系统查看他们的借阅历史,保存材料,并续借物品

  • 借阅资料
  • 使用library的resource
  • 查看借阅
  • place holds on materials
  • 续借materials

Library Staff

负责管理图书馆的运作。他们可能能够向顾客检查材料,处理新材料,并管理目录

  • check materials towards usr
  • deal new materials
  • manage catalog

Admin(programmer)

建立和维护图书馆管理系统的用户。他们可能能够创建和删除用户帐户,为不同的用户角色设置权限,并管理系统的设置。

  • 创建用户
  • 删除用户
  • set different rights
  • 管理系统的设置(deal with…)

Super usr

这些用户拥有library staff和admin的所有权限。他们可能负责监督图书馆的运作,并确保系统平稳运行。

Guests(游客)

  • 查看图书馆的目录
  • 搜索资料

不能:

  • 借阅资料
  • 登录系统
搜索
匹配结果数:
未搜索到匹配的文章。