日度归档:27 3 月, 2021

CSP 202012-3 带配额的文件系统

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import copy

file_template = {
    "isDirectory": False,
    "fileSize": 0,
    "childSize": 0,
    "childQuota": 0,
    "descendantQuota": 0,
    "descendants": {}
}
root_directory = {
    "isDirectory": True,
    "fileSize": 0,
    "childSize": 0,
    "childQuota": 0,
    "descendantQuota": 0,
    "descendants": {}
}

def filepath_resolver(filepath: str):
    fpArr = filepath.split('/')
    fpArr.pop(0)
    return fpArr

def visit(filepath):
    if filepath == '/':
        return root_directory
    fpArr = filepath_resolver(filepath)
    fileIter = root_directory
    try:
        for file in fpArr:
            fileIter = fileIter["descendants"][file]
    except KeyError:
        return None
    return fileIter

def checkQuotaLimit(fileIter, filesize, descendants = True, child = True):
    if descendants:
        if fileIter["descendantQuota"] != 0:  # 检查后代文件配额
            if fileIter["fileSize"] + filesize > fileIter["descendantQuota"]:
                return False
    if child:
        if fileIter["childQuota"] != 0:  # 检查孩子文件配额
            if fileIter["childSize"] + filesize > fileIter["childQuota"]:
                return False
    return True

def create(filepath, filesize, isDirectory = False):
    dstIter = visit(filepath)
    update_filesize = filesize
    if dstIter is not None:
         update_filesize -= dstIter["fileSize"]

    fpArr = filepath_resolver(filepath)
    fileIter = root_directory
    for i in range(len(fpArr)):
        file = fpArr[i]
        if file not in fileIter["descendants"].keys(): # 无该目录/文件
            curFile = copy.deepcopy(file_template)
            if i != len(fpArr) - 1: # 非末端文件
                if not checkQuotaLimit(fileIter, update_filesize, True, False): return False
                curFile["isDirectory"] = True
            else: # 末端文件
                if not checkQuotaLimit(fileIter, update_filesize): return False
                curFile["isDirectory"] = isDirectory
                curFile["fileSize"] = filesize
            fileIter["descendants"][file] = curFile
        else: # 存在该目录/文件
            curFile = fileIter["descendants"][file]
            if i != len(fpArr) - 1: # 非末端文件
                if not curFile["isDirectory"]: # 欲进入的新目录文件与普通文件重名
                    return False
                else:
                    if not checkQuotaLimit(fileIter, update_filesize, True, False): return False
            else: # 末端文件
                if curFile["isDirectory"] != isDirectory: # 欲创建的同名新文件与旧文件类型冲突
                    return False
                else: # 文件已存在,替换文件大小
                    if not checkQuotaLimit(fileIter, update_filesize): return False
                    curFile["fileSize"] = filesize
        fileIter = fileIter["descendants"][file]

    fileIter = root_directory
    for i in range(len(fpArr)):
        file = fpArr[i]
        fileIter["fileSize"] += update_filesize
        if i == len(fpArr) - 1:
            fileIter["childSize"] += update_filesize
        fileIter = fileIter["descendants"][file]
    return True

def remove(filepath):
    fpArr = filepath_resolver(filepath)
    dstIter = visit(filepath)
    if dstIter is None:
        return True

    fileIter = root_directory
    for file in fpArr:
        fileIter["fileSize"] -= dstIter["fileSize"]
        if fileIter["descendants"][file] == dstIter:
            if not dstIter["isDirectory"]:
                fileIter["childSize"] -= dstIter["fileSize"]
            break
        fileIter = fileIter["descendants"][file]
    fileIter["descendants"].pop(fpArr[-1])
    return True

def quota(filepath, child_quota, descendant_quota):
    dstIter = visit(filepath)
    if dstIter is None:
        return False
    if not dstIter["isDirectory"]:
        return False
    child_flag = child_quota == 0 or dstIter["childSize"] <= child_quota
    descendant_flag = descendant_quota == 0 or dstIter["fileSize"] <= descendant_quota
    if child_flag and descendant_flag:
        dstIter["childQuota"] = child_quota
        dstIter["descendantQuota"] = descendant_quota
        return True
    else:
        return False

def main():
    n = int(input())
    for loop in range(n):
        cmd = input().split()
        result = False
        if cmd[0] == "C":
            result = create(cmd[1], int(cmd[2]))
        elif cmd[0] == "R":
            result = remove(cmd[1])
        else:
            result = quota(cmd[1], int(cmd[2]), int(cmd[3]))
        if result:
            print("Y")
        else:
            print("N")
        # print(root_directory)

if __name__ == '__main__':
    main()