牛客刷题-Day16
牛客刷题-Day16
今日刷题:\(1016-1020\)
1017 Efficient Solutions
题目描述
The princess of Centauri Prime is the galaxy’s most eligible bachelorette of the year. She has hopeful grooms lined up in front of the royal palace for a chance to spend \(5\) minutes to try and impress her. After \(5\) minutes, the gentleman is carried out of the royal chambers by the palace guards, and the
princess makes a decision. She rates the lad on his lineage and charm by giving him a score for each of the two properties. On Centauri Prime, low scores are better than high scores.
Suppose that she observes two gentlemen - \(A\) and \(B\). She assigns \(A\) the scores \(LA\) and \(CA\) (for
lineage and charm, respectively). \(B\) receives scores \(LB\) and \(CB\). Then \(A\) is dominated by \(B\) if either
• \(LB < LA\) and \(CB ≤ CA\), or
• \(LB ≤ LA\) and \(CB < CA\).
In other words, if at least one of \(B\)’s scores is better than \(A\)’s, and the other score is not worse. She considers a gentleman to be efficient (or Pareto-optimal) if she has not yet met any other gentleman who dominates him. She maintains a list of efficient grooms and updates it after each \(5\)-minute presentation.
Given the queue of bachelors and the scores assigned to them by the princess, determine the number of entries in the list of efficient grooms after each performance.
输入描述
The first line of input gives the number of cases, \(N (0 < N < 40)\). \(N\) test cases follow.
Each one starts with a line containing \(n (0 ≤ n ≤ 15000)\) — the size of the queue. The next \(n\) lines will each contain two scores (integers in the range \([0, 10^9]\)). Initially, the list is empty.
输出描述
For each test case, output one line containing ‘Case #x:’ followed by \(n\) lines, line \(i\) containing the size
of the list of efficient grooms after the \(i\)-th update. Print an empty line between test cases.
示例
输入
4
1
100 200
2
100 200
101 202
2
100 200
200 100
5
11 20
20 10
20 10
100 20
1 1
输出
Case #1:
1
Case #2:
1
1
Case #3:
1
2
Case #4:
1
2
3
3
1
解题思路
参考:UVA11020 Efficient Solutions
根据题意,对于 \(A\) 如果存在一个元素比它有优势,则该元素位于 \(A\) 的左下角。也就是说,如果集合中的元素都没有对其有优势的元素,则整体呈现为一个二维坐标中向下凹的曲线。
按照 \(L\) 和 \(C\) 从小到大排序。
现在考虑插入一个元素,在坐标系中往左边看,判断能否插入。要找到 \(L\) 小于它的元素中 \(C\) 最小的元素,这个元素是最有可能使它失去优势的。\(L\) 越大 \(C\) 越小,因此需要找到最后一个 \(L\) 小于它或者 \(L\) 等于它但 \(C\) 小于等于它的元素。使用 lower_bound 找到第一个 \(L\) 大于它或者 \(L\) 等于它但 \(C\) 大于等于它的元素,这个元素的前一个元素就是要找的元素。如果没有找到,或者找到的元素 \(C\) 大于它,那么它就能插入,否则不能。
也就是确定集合中不存在优势于目前考虑元素的元素。
如果能插入,在坐标系中往右边看,开始排除后面需要删除的元素。要删除所有 \(L\) 大于它且 \(C\) 大于等于它或者 \(L\) 等于它且 \(C\) 大于它的元素。因此从第一个 \(L\) 大于它或者 \(L\) 等于它但 \(C\) 大于它的元素开始删除,用 upper_bound 实现。随后开始向后遍历,我们只要删除到第一个 \(C\) 小于它的元素之前即可,后面的 \(C\) 更小不需要考虑。
最后容器大小就是有竞争力的人的人数。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 15010;
int T, n;
struct Node {
int l, c;
bool operator < (const struct Node &w) const {
if (l == w.l)
return c < w.c;
return l < w.l;
}
} a[N];
multiset<Node> s;
int main() {
scanf("%d", &T);
for (int t = 1; t <= T; t++) {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].l, &a[i].c);
printf("Case #%d:\n", t);
for (int i = 1; i <= n; i++) {
auto it = s.lower_bound(a[i]);
if (it == s.begin() || (--it)->c > a[i].c) {
s.insert(a[i]);
it = s.upper_bound(a[i]);
while(it != s.end() && it->c >= a[i].c)
s.erase(it++);
}
printf("%d\n", s.size());
}
printf("\n");
s.clear();
}
return 0;
}
1018 Defeat the Enemy
题目描述
Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. One day, there is another tribe become their target. The strong tribe has decide to terminate them!!! There are m villages in the other tribe. Each village contains a troop with attack power \(EAttack_i\), and defense power \(EDefense_i\). Our tribe has n troops to attack the enemy. Each troop also has the attack power \(Attack_i\), and defense power \(Defense_i\). We can use at most one troop to attack one enemy village and a troop can only be used to attack only one enemy village. Even if a troop survives an attack, it can’t be used again in another attack.
The battle between \(2\) troops are really simple. The troops use their attack power to attack against the other troop simultaneously. If a troop’s defense power is less than or equal to the other troop’s attack power, it will be destroyed. It’s possible that both troops survive or destroy.
The main target of our tribe is to destroy all the enemy troops. Also, our tribe would like to have most number of troops survive in this war.
输入描述
The first line of the input gives the number of test cases, \(T\). \(T\) test cases follow. Each test case start with \(2\) numbers \(n\) and \(m\), the number of our troops and the number of enemy villages. \(n\) lines follow, each with \(Attack_i\) and \(Defense_i\), the attack power and defense power of our troops. The next \(m\) lines describe the enemy troops. Each line consist of \(EAttack_i\) and \(EDefense_i\), the attack power and defense power of enemy troops.
Limits:
\(1≤ T ≤10^6\),
\(1≤ n,m ≤10^5\),
\(1≤ Attack_i,Defense_i,EAttack_i,EDefense_i ≤10^9\).
保证 \(n\) 的总和不超过 \(10^6\),\(m\) 的总和不超过 \(10^6\)。
输出描述
For each test ease, output one line containing ‘Case #x: y’, where \(x\) is the test case number (starting from \(1\)) and \(y\) is the max number of survive troops of our tribe. If it‘s impossible to destroy all enemy troops, output -1 instead.
示例
输入
2
3 2
5 7
7 3
1 2
4 4
2 2
2 1
3 4
1 10
5 6
输出
Case #1: 3
Case #2: -1
解题思路
对于军队按照攻击力降序排序,敌军按照防御力降序排序。
假设军队和敌军已消耗部分,剩余的军队存在攻击力小于敌军防御力的情况,则敌军无法消灭,输出 -1。
否则如果对于一个敌军,存在多个军队可以消灭它,则在保证存活的情况下选择防御力最小(但是大于敌军攻击力)的军队,如果无法保证存活,则选择防御力最小的军队损失。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int T;
int n, m;
struct Node {
int a, d;
} a[N], b[N];
bool cmp1(Node a, Node b) { // 攻击力降序
return a.a > b.a;
}
bool cmp2(Node a, Node b) { // 防御力降序
return a.d > b.d;
}
bool solve() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].a, &a[i].d);
for (int i = 1; i <= m; i++)
scanf("%d%d", &b[i].a, &b[i].d);
sort(a + 1, a + n + 1, cmp1);
sort(b + 1, b + m + 1, cmp2);
int cnt = n;
multiset<int> s;
for (int i = 1, j = 1; j <= m; j++) {
while (i <= n && a[i].a >= b[j].d) // 能摧毁
s.insert(a[i++].d);
if (s.empty()) return false;
auto it = s.upper_bound(b[j].a); // 第一个防御力大于攻击力
if (it == s.end()) { // 不存在
s.erase(s.begin()); // 损失防御力最小的
cnt--;
} else {
s.erase(it);
}
}
printf("%d\n", cnt);
return true;
}
int main() {
scanf("%d", &T);
for (int t = 1; t <= T; t++) {
printf("Case #%d: ", t);
bool flag = solve();
if (!flag)
puts("-1");
}
return 0;
}
1019 Let'sPlayCurling
题目描述
Curling is a sport in which players slide stones on a sheet of ice toward a target area. The team with the nearest stone to the center of the target area wins the game.
Two teams, Red and Blue, are competing on the number axis. After the game there are \((n+m)\) stones remaining on the axis, \(n\) of them for the Red team and the other \(m\) of them for the Blue. The \(i\)-th stone of the Red team is positioned at \(a_i\) and the \(i\)-th stone of the Blue team is positioned at \(b_i\).
Let \(c\) be the position of the center of the target area. From the description above we know that if there exists some \(i\) such that \(1≤i≤n\) and for all \(1≤j≤m\) we have \(∣c−a_i∣<∣c−b_j∣\) then Red wins the game. What's more, Red is declared to win \(p\) points if the number of \(i\) satisfying the constraint is exactly \(p\).
Given the positions of the stones for team Red and Blue, your task is to determine the position \(c\) of the center of the target area so that Red wins the game and scores as much as possible. Note that \(c\) can be any real number, not necessarily an integer.
输入描述
There are multiple test cases. The first line of the input contains an integer \(T\) indicating the number of test cases. For each test case:
The first line contains two integers \(n\) and \(m (1≤n,m≤10^5)\) indicating the number of stones for Red and the number of stones for Blue.
The second line contains \(n\) integers \(a_1,a_2,⋯,a_n(1≤a_i≤10^9)\) indicating the positions of the stones for Red.
The third line contains \(m\) integers \(b_1,b_2,⋯,b_m(1≤b_i≤10^9)\) indicating the positions of the stones for Blue.
It's guaranteed that neither the sum of \(n\) nor the sum of \(m\) will exceed \(5×10^5\).
输出描述
For each test case output one line. If there exists some \(c\) so that Red wins and scores as much as possible, output one integer indicating the maximum possible score of Red (NOT \(c\)). Otherwise output "Impossible" (without quotes) instead.
示例
输入
3
2 2
2 3
1 4
6 5
2 5 3 7 1 7
3 4 3 1 10
1 1
7
7
输出
2
3
Impossible
备注
For the first sample test case we can assign \(c=2.5\) so that the stones at position \(2\) and \(3\) for Red will score.
For the second sample test case we can assign \(c=7\) so that the stones at position \(5\) and \(7\) for Red will score.
解题思路
可以发现,如果 \(c\) 在某个红色的区间内部,则该区间内的红色点以及所有的蓝色点都可以满足条件 \(∣c−a_i∣<∣c−b_j∣\)。那么这样问题就转变为求解包含最多红色点的区间。使用 \(Map\) 进行计数,如果某点为蓝色,对应红色点数为 \(0\),遍历 \(Map\) 统计。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int T;
int n, m, red, blue;
bool solve() {
map<int, int> s;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &red);
s[red]++;
}
for (int i = 1; i <= m; i++) {
scanf("%d", &blue);
s[blue] = 0;
}
int ans = 0, cnt = 0;
for (auto [k, v]: s) {
if (v) cnt += v;
else cnt = 0;
ans = max(ans, cnt);
}
if (!ans)
return false;
printf("%d\n", ans);
return true;
}
int main() {
scanf("%d", &T);
while (T--) {
if (!solve())
puts("Impossible");
}
return 0;
}
1020 Rinne Loves Data Structure
题目描述
\(Rinne\) 喜欢 \(OI\)。在 \(9102\) 年的 \(PION\) 中,她在初赛遇到了这样一道题目:
阅读下列代码,然后回答问题。

补充:建树过程中会更新 \(lc\) 和 \(rc\),这实质上是一个二叉查找树的插入过程。定义一个玄学节点叫做 \(R\),每次操作读入 \(val\),执行 \(Insert(R,val)\)。
问题:每次 \(Insert\) 操作结束之后,输出当前节点的深度和。
这里我们定义 \(R\) 节点的深度为 \(0\)。
输入描述
第一行一个整数 \(N\),表示操作次数。
接下来 \(N\) 行,第 \(i\) 行有一个值 \(val_i\),表示第 \(i\) 次操作的 \(val_i\)。
输出描述
\(N\) 行,每行输出该次操作完后的答案。
示例
输入
8
3
5
1
6
8
7
2
4
输出
0
1
2
4
7
11
13
15
备注
\(N≤3×10^5\)。
解题思路
NC22596 Rinne Loves Data Structure
C++ 代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
unordered_map<int, int> dep;
set<int> s;
ll ans = 0;
while (n--) {
int val;
cin >> val;
if (s.empty()) {
s.insert(val);
dep[val] = 0;
cout << 0 << '\n';
continue;
}
auto pos = s.lower_bound(val);
if (*pos == val) {
cout << ans << '\n';
continue;
}
if (pos == s.begin()) dep[val] = dep[*pos] + 1;
else if (pos == s.end()) pos--, dep[val] = dep[*pos] + 1;
else {
dep[val] = dep[*pos];
pos--;
dep[val] = max(dep[*pos], dep[val]) + 1;
}
ans += dep[val];
s.insert(val);
cout << ans << '\n';
}
return 0;
}
本文来自博客园,作者:Cocoicobird,转载请注明原文链接:https://www.cnblogs.com/Cocoicobird/p/19152804
浙公网安备 33010602011771号