题目大意

给出n个文件的路径和大小,然后要像Windows资源管理器的侧边栏那样输出文件夹的分层结构。当一个文件夹里的所有子文件夹大小都不超过t时,它会折叠起来。

题目分析

模拟题,集训的时候打崩了。关键是建树的过程,将路径拆分成文件夹名的vector,然后利用这个vector创建这个路径上的所有文件夹的结点。

所有结点按创建次序保存在数组中,每一个结点包含一个map, 存放它的子节点,“文件夹名”到结点位置的映射。

这样一来,这道题就很好写了。

source code

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <iostream>
using namespace std;
struct dir{
string name;
int sz;
map<string, int> subdir;
}a[60000];
int tot = 0, t;

void addFile(vector<string> &path, int pi, int sz, int ai) {
a[ai].sz += sz;
if (pi >= path.size()) return;
if (!a[ai].subdir.count(path[pi])) {
a[++tot].name = path[pi];
a[ai].subdir[path[pi]] = tot;
}
addFile(path, pi + 1, sz, a[ai].subdir[path[pi]]);
}

bool canFold(int ai) {
for (auto i:a[ai].subdir) if (a[i.second].sz >= t) return false;
return true;
}

void printDir(int ai = 0, string ps = "") {

ps += a[ai].name + "/";
if (a[ai].subdir.empty()) {
printf(" %s %d\n", ps.c_str(), a[ai].sz);
}
else if (canFold(ai)) {
printf("+ %s %d\n", ps.c_str(), a[ai].sz);
}
else {
printf("- %s %d\n", ps.c_str(), a[ai].sz);
for (auto i:a[ai].subdir) printDir(i.second,ps);
}
}


char str[1024];
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int sz;
scanf("%s%d", str, &sz);
vector<string> path;
string buf;
int len = strlen(str);
for (int i = 1; i < len; i++) {
if (str[i] == '/') path.push_back(buf),buf.clear();
else buf += string(1, str[i]);
}
addFile(path, 0, sz, 0);
}
scanf("%d", &t);
printDir();
}