Alice and Bob(贪心 + multiset)

本文深入探讨了游戏开发领域的关键技术,包括游戏引擎、编程语言、硬件优化等,并重点阐述了AI音视频处理的应用场景和实现方法,如语义识别、物体检测、语音变声等。通过实例分析,揭示了技术融合带来的创新解决方案。

Alice and Bob

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2571    Accepted Submission(s): 828


Problem Description
Alice and Bob's game never ends. Today, they introduce a new game. In this game, both of them have N different rectangular cards respectively. Alice wants to use his cards to cover Bob's. The card A can cover the card B if the height of A is not smaller than B and the width of A is not smaller than B. As the best programmer, you are asked to compute the maximal number of Bob's cards that Alice can cover.
Please pay attention that each card can be used only once and the cards cannot be rotated.
 

 

Input
The first line of the input is a number T (T <= 40) which means the number of test cases.
For each case, the first line is a number N which means the number of cards that Alice and Bob have respectively. Each of the following N (N <= 100,000) lines contains two integers h (h <= 1,000,000,000) and w (w <= 1,000,000,000) which means the height and width of Alice's card, then the following N lines means that of Bob's.
 

 

Output
For each test case, output an answer using one line which contains just one number.
 

 

Sample Input
2
2
1 2
3 4
2 3
4 5
3
2 3
5 7
6 8
4 1
2 5
3 4
 

 

Sample Output

 

1
2

       题意:

       首先给出样例个数 T(1 ~ 50),每个样例给出 N (<= 100000)张牌,代表 Alice 和 Bob 各有 N 张牌,每张牌都有长(1 ~ 10 ^ 9)和宽(1 ~ 10 ^ 9),现要用 Alice 的牌去覆盖 Bob 的,必须长和宽都大于等于才能覆盖,问能够覆盖的最大数。

 

       思路:

       贪心 + multiset。与昨天的多校贪心题类似,先对牌统一按长由大到小排序,后用 Bob 的牌去匹配 Alice 的牌,选出 Alice 牌中长大于 Bob 长的牌,将宽放入 multiset 中,在从中选出在里面的牌中大于或者等于 Bob 牌的宽的第一个数,运用 upper_bound,之后从 multiset 中删去这张牌即可。用 multiset 的原因是可能宽度会有重复的。寻找的时候统计个数就好了。

       lower_bound 返回的是第一个大于或者等于 num的数,若全部都小于则返回 end;

       upper_bound 返回的是第一个大于 num 的数,若全部都小于则返回 end。

 

       AC:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

const int MAX = 100005;

typedef struct {
        int l, w;
} node;

node a[MAX], b[MAX];

bool cmp (node a, node b) {
        if (a.l != b.l) return a.l > b.l;
        return a.w > b.w;
}

int main() {
        int t;
        scanf("%d", &t);

        while (t--) {
                int n;
                scanf("%d", &n);

                for (int i = 0; i < n; ++i) {
                        scanf("%d%d", &a[i].l, &a[i].w);
                }

                for (int i = 0; i < n; ++i) {
                        scanf("%d%d", &b[i].l, &b[i].w);
                }

                sort(a, a + n, cmp);
                sort(b, b + n, cmp);

                int m = 0, ans = 0;
                multiset<int> s;
                for (int i = 0; i < n; ++i) {
                        while (m != n && a[m].l >= b[i].l) {
                                s.insert(a[m].w);
                                ++m;
                        }

                        multiset<int>::iterator it;
                        it = s.lower_bound(b[i].w);

                        if (it != s.end() && *it >= b[i].w) {
                                ++ans;
                                s.erase(it);
                        }
                }

                printf("%d\n", ans);
        }
}

 

 

 

 

1. std::vector —— 动态数组 ✅ 特点: 底层为连续内存的动态数组; 支持随机访问(O(1) 下标访问); 可以动态扩容(自动双倍增长); 是最常用、最灵活的容器。 ⏱ 时间复杂度: 操作 复杂度 访问元素 vec[i] O(1) 尾部插入/删除 push_back/pop_back 均摊 O(1) 中间插入/删除 O(n) 查找元素 O(n) 📌 使用场景: 替代普通数组,避免手动管理大小; 存图(邻接表)、存储输入数据、DP 数组等; 实现栈或队列(配合 push_back 和 pop_back); 💡 示例代码: 🔧 技巧: 使用 vec.reserve(n) 预分配空间,避免频繁扩容; vector<bool> 是特化版本,行为异常,慎用。 2. std::queue 和 std::priority_queue —— 队列与优先队列 ✅ std::queue 先进先出(FIFO)结构。 常用于 BFS、模拟任务调度等。 主要操作: 示例(BFS): ✅ std::priority_queue 默认是最大堆,顶部始终是最大元素; 常用于 Dijkstra、Huffman 编码、贪心算法等。 默认行为(大根堆): C++ std::priority_queue<int> pq; pq.push(3); pq.push(1); pq.push(4); std::cout << pq.top(); // 输出 4 小根堆写法: C++ std::priority_queue<int, std::vector<int>, std::greater<int>> min_pq; 自定义比较(结构体): ⚠️ 注意:priority_queue 不支持修改已有元素,也不能遍历。 3. std::stack —— 栈 后进先出(LIFO),适合 DFS、括号匹配、表达式求值等。 常用操作: C++ s.push(x); s.pop(); // 无返回值 s.top(); // 返回栈顶 示例: 4. std::deque —— 双端队列 双向队列,可在头尾高效插入/删除; 支持随机访问; push_front, pop_front, push_back, pop_back 均为 O(1); vector 扩容时会失效迭代器,而 deque 更稳定。 使用场景: 单调队列(滑动窗口最大值); BFS 中需要从前或后插入的情况; 实现双端队列类问题。 示例: 5. std::set / std::multiset —— 有序集合 ✅ std::set 内部基于红黑树实现,自动排序且去重; 插入、删除、查找均为 O(log n); 不支持下标访问,但可用迭代器遍历。 常用操作: 使用场景: 动态维护一个有序唯一集合; 查询前驱/后继(lower_bound / upper_bound); 替代平衡树。 ✅ std::multiset 允许重复元素的 set; 同样有序,支持 insert, erase, find, lower_bound 等; 删除单个元素时使用 erase(s.find(x)) 防止全部删除; erase(x) 会删掉所有等于 x 的元素! 6. std::map / std::unordered_map —— 关联容器(键值对) ✅ std::map 键值对容器,按键有序排列(红黑树); 插入、查找、删除:O(log n); 键自动排序,可遍历得到有序结果。 示例: ✅ std::unordered_map 基于哈希表实现; 平均操作复杂度 O(1),最坏 O(n); 不保证顺序; 在竞赛中常用于快速映射(如字符串 → ID、计数等)。 示例: C++ std::unordered_map<std::string, int> cnt; cnt["apple"]++; cnt["banana"]++; ⚠️ 注意事项: 哈希碰撞可能导致被卡(尤其在线评测系统),可加随机扰动防 hack; 对自定义类型需提供 hash 函数,否则不支持。 7. std::array —— 固定大小数组(C++11 起) 类似内置数组,但更安全、支持 STL 操作; 大小在编译期确定; 性能极高,适用于固定长度的小数组。 示例: C++ std::array<int, 5> arr = {1, 2, 3, 4, 5}; for (int x : arr) std::cout << x << " "; 8. std::pair 和 std::tuple —— 组合类型 ✅ std::pair<T1, T2> 存储两个元素的组合; 常用于 map 键值、priority_queue 中带权值的节点; 支持字典序比较(<),便于排序。 示例: C++ std::pair<int, std::string> p = {3, "hello"}; std::vector<std::pair<int, int>> edges; edges.push_back({u, v}); ✅ std::tuple 多元组,可存多个不同类型元素; 使用 std::make_tuple, std::tie, std::get 操作。 C++ auto t = std::make_tuple(1, "abc", 3.14); int a; std::string b; double c; std::tie(a, b, c) = t; 9. 其他实用技巧与组合使用 场景 推荐容器组合 图的邻接表表示 vector<vector<int>> 或 vector<vector<pair<int, int>>>(带权) 并查集 vector<int> 存 parent 数组 字符串哈希映射 unordered_map<string, int> 滑动窗口最大值 deque<int> 实现单调队列 Top-K 问题 priority_queue<int>(小根堆维护 K 个最大) 动态排名查询 set<int> + distance(s.begin(), it)(但慢,可用 PBDS 替代) ❗常见陷阱提醒 错误 正确做法 map[key] 会创建默认值,可能改变结构 查找用 find() 避免插入 vector 迭代器在 push_back 后可能失效 使用索引或重新获取 erase(remove(...)) 忘记写法 vec.erase(std::remove(vec.begin(), vec.end(), x), vec.end()); priority_queue 无法遍历 若需遍历,改用 vector + make_heap 或排序 unordered_map 被哈希攻击 加随机种子或切换到 map 给出以上内容的对应代码,并且简要注释功能
最新发布
10-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值