题目链接: https://codeforces.com/gym/101620
题意:有一个文件夹系统,现在给你n个文件的绝对路径,你需要按字典序输出所有占用内存大于k的文件夹,如果文件夹下面还有文件夹,但是没有展示则在前方加上符号‘+’,如果该文件夹下面只有文件则前方用空格占位,否则前方输出符号‘-’。其实不懂的可以直接参照windows的系统文件显示。
解题心得:
- 首先要知道其实文件的储存就是一棵树,所以这个题最后肯定是要建一棵树来解决的。
- 其次是不能简单的直接把每个文件夹名字映射成数字,因为可能有相同的文件夹的名字,只要不是在同一个文件夹下有相同的名字就都可以满足。对于这个可以用这个文件的绝对路径当成这个文件的名字,然后按字典序映射成数字,建树遍历。
代码有点丑,辣眼睛
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const double INF = 1e9;
struct Node {
ll va, to, va2;
}node[maxn*10000];
vector <string> ve;
vector <string> s;
vector <ll> edge[maxn*10000];
ll n, num[maxn], root, k;
map <string, ll> maps, mapsVa;
ll vis[maxn*10000];//vis[i]==1代表这个节点是文件,vis[i]==2代表这个节点下面全是文件,否则是继续混合展开
void init() {
scanf("%lld", &n);
for(ll i=1;i<=n;i++) {
string st;
cin>>st;
s.push_back(st);
scanf("%lld", &num[i]);
mapsVa[st] = num[i];
}
scanf("%lld", &k);
}
void mapNum() {
for(ll i=0;i<s.size();i++) {
string st = s[i], temp;
temp.clear();
for(ll j=0;j<st.length();j++) {
temp += st[j];
if(j == st.length()-1) {
ve.push_back(temp);
break;
}
if(st[j] == '/') {
ve.push_back(temp);
}
}
}
sort(ve.begin(), ve.end());
ve.erase(unique(ve.begin(), ve.end()), ve.end());
for(ll i=0;i<ve.size();i++) {
maps[ve[i]] = i;
}
root = maps["/"];
}
void build_tree() {
for(ll i=0;i<s.size();i++) {
string st = s[i], temp;
temp.clear();
ll pre = -1, now = -1;
for(ll j=0;j<st.length();j++) {
temp += st[j];
if(j == st.length()-1) {
if(now != -1)
pre = now;
now = maps[temp];
edge[pre].push_back(now);
edge[now].push_back(pre);
node[now].va = mapsVa[temp];
vis[now] = 1;
break;
}
if(st[j] == '/') {
ve.push_back(temp);
if(pre == -1) {
pre = maps[temp];
} else {
if(now != -1)
pre = now;
now = maps[temp];
edge[pre].push_back(now);
edge[now].push_back(pre);
}
continue;
}
}
}
for(ll i=0;i<maxn*10000;i++) {
if(edge[i].empty()) break;
sort(edge[i].begin(), edge[i].end());
edge[i].erase(unique(edge[i].begin(), edge[i].end()), edge[i].end());
}
}
ll dfs(ll pre,ll now) {
if(edge[now].size() == 1 && now != root) {
return node[now].va;
}
bool flag = true, all_small = true;
for(ll i=0;i<edge[now].size();i++) {
ll to = edge[now][i];
if(to == pre) continue;
node[now].va += dfs(now, to);
}
for(ll i=0;i<edge[now].size();i++) {
ll to = edge[now][i];
if(to == pre) continue;
if(vis[to] != 1) flag = false;
if(vis[to] != 1 && node[to].va >= k) all_small = false;
}
if(flag) vis[now] = 2;
else if(all_small) vis[now] = 3;
return node[now].va;
}
void Print(ll pre, ll now) {
if(vis[now] == 1) return ;
if(vis[now] == 2) {
printf(" ");
cout<<ve[now]<<" ";
printf("%lld\n", node[now].va);
return ;
} else if(vis[now] == 3){
printf("+ ");
cout<<ve[now]<<" ";
printf("%lld\n", node[now].va);
return ;
} else {
printf("- ");
cout<<ve[now]<<" ";
printf("%lld\n", node[now].va);
}
for(ll i=0;i<edge[now].size();i++) {
ll v = edge[now][i];
if(v == pre) continue;
Print(now, v);
}
}
int main() {
// freopen("1.in.txt", "r", stdin);
init();
mapNum();
build_tree();
dfs(-1, root);
Print(-1, root);
return 0;
}