考虑一个简易文件管理器,用户可以通过管理器对某个目录下文件最大/小、文件名字典序最大/小的文件进行排序,此外其具有删除和添加文件的功能。输入保证目录只有一级。
输入格式:第1行输入一个Q(1<=Q<=100000),表示操作的次数;第2-Q+1行输入一行操作序列。
操作序列的格式为 op args,当op=1,即第一种操作时,args的格式为 folder name size,表示将在某个folder目录下添加文件名为name的文件,文件大小为size,如果文件名重复,则删除原来的文件再进行添加操作;
当op=2时,args的格式为 folder name,表示将要在某个folder目录下删除文件名为name的文件,如果文件名不存在,操作不执行;
当op=3时,args的格式为 folder k,表示输出某个目录下文件大小最大至第k大的文件名,如果大小相同按文件名数字从小到大输出,如果不满k个文件只需要输出已有的文件名,如果文件夹为空或不存在则输出一个空行;
当op=4时,args的格式为 folder k,表示输出某个目录下文件名数字大小最小至第k小的文件名,如果不满k个文件只需要输出已有的文件名,如果文件夹为空或不存在则输出一个空行;注意:输出文件名以空格隔开,不输出多余的换行和空格。

#include <iostream>
#include <map>
#include <vector>
#include <set>
using namespace std;
// 定义一个文件名和文件大小的pair类型
typedef pair<int, int> part;
// 自定义比较器,用于按文件大小降序排序;如果大小相同,则按文件名升序排序
struct cmp_by_value {
bool operator()(const part& p1, const part& p2) const {
if (p1.second == p2.second) {
return p1.first < p2.first; // 如果文件大小相同,则按文件名升序排序
}
return p1.second > p2.second; // 否则按文件大小降序排序
}
};
// 定义一个结构体表示每个文件夹,包含文件名到文件大小的映射以及按文件大小排序的集合
struct NodeLink {
map<int, int> m; // 存储文件名到文件大小的映射,用于快速查找文件
set<part, cmp_by_value> s; // 存储按文件大小排序的文件集合
};
// 添加或更新文件夹中的文件
void add(vector<NodeLink>& v, int folder, int name, int size) {
map<int, int>& m = v[folder - 1].m; // 获取指定文件夹的文件映射
set<part, cmp_by_value>& s = v[folder - 1].s; // 获取指定文件夹的按文件大小排序的集合
auto it = m.find(name); // 查找文件是否已存在
if (it != m.end()) {
s.erase({name, it->second}); // 如果文件已存在,先从集合中移除旧的文件信息
}
s.insert({name, size}); // 将新的文件信息插入集合中
m[name] = size; // 更新映射中的文件信息
}
// 从文件夹中删除文件
void del(vector<NodeLink>& v, int folder, int name) {
map<int, int>& m = v[folder - 1].m; // 获取指定文件夹的文件映射
set<part, cmp_by_value>& s = v[folder - 1].s; // 获取指定文件夹的按文件大小排序的集合
auto it = m.find(name); // 查找文件是否存在
if (it != m.end()) {
s.erase({name, it->second}); // 如果文件存在,从集合中移除该文件信息
m.erase(it); // 从映射中删除该文件
}
}
// 输出文件夹中文件大小从大到小的前k个文件名
void outbyvalue(const vector<NodeLink>& v, int folder, int k) {
const set<part, cmp_by_value>& s = v[folder - 1].s; // 获取指定文件夹的按文件大小排序的集合
int count = 0; // 计数器,用于输出前k个文件名
for (auto it = s.begin(); it != s.end() && count < k; ++it, ++count) {
if (count > 0) cout << " "; // 输出多个文件名时,用空格隔开
cout << it->first;
}
cout << endl;
}
// 输出文件夹中文件名从小到大的前k个文件名
void outbykey(const vector<NodeLink>& v, int folder, int k) {
const map<int, int>& m = v[folder - 1].m; // 获取指定文件夹的文件映射
int count = 0; // 计数器,用于输出前k个文件名
for (auto it = m.begin(); it != m.end() && count < k; ++it, ++count) {
if (count > 0) cout << " "; // 输出多个文件名时,用空格隔开
cout << it->first;
}
cout << endl;
}
// 主函数,处理输入并执行相应的操作
int main() {
int n;
cin >> n; // 输入操作次数
vector<NodeLink> v(n); // 定义文件夹的向量
for (int i = 0; i < n; i++) {
int op;
cin >> op; // 输入操作类型
switch (op) {
case 1: {
int folder, m_name, m_size;
cin >> folder >> m_name >> m_size; // 输入文件夹编号、文件名和文件大小
add(v, folder, m_name, m_size); // 调用add函数添加文件
break;
}
case 2: {
int folder, m_name;
cin >> folder >> m_name; // 输入文件夹编号和文件名
del(v, folder, m_name); // 调用del函数删除文件
break;
}
case 3: {
int folder, k;
cin >> folder >> k; // 输入文件夹编号和k值
outbyvalue(v, folder, k); // 按文件大小排序输出前k个文件名
break;
}
case 4: {
int folder, k;
cin >> folder >> k; // 输入文件夹编号和k值
outbykey(v, folder, k); // 按文件名排序输出前k个文件名
break;
}
}
}
}

被折叠的 条评论
为什么被折叠?



