csp 202012-3
起因
又通知csp认证,可是这个好贵呀,刷一刷历年考题感觉第三题还有点意思,软件工程那种味道,不过我的算法水平也不怎样就是了.
经过
于是就卡在这个题上了.
最近看了一点操作系统就想试试.
过了两个样例,结果只有20分 xp
我加了一个print文件系统的函数,每一步操作之后把整个文件系统写入stderr
,
结果,又整出几个bug,再继续,我又通过硬看代码,找出一个错误,提交之后,显示超时,我真是无话可说,来来去去看了几遍,找不到错误.
于是我又整了一个随机数据生成器,有用别人的100%代码,对比输出结果.
# datagen.py
from random import randint
def randname():
return chr(randint(0,7)+ord('A'))+str(randint(0,5))
def randpath(low=1):
n=randint(low,20)
return '/'+'/'.join(randname() for i in range(n))
def randcmd():
r=randint(0,2)
if r==0:
return 'C %s %d' % (randpath(1),randint(0,1e9))
elif r==1:
return 'R %s' % randpath(1)
else:
return 'Q %s %d %d' % (randpath(),randint(0,1e18),randint(0,1e18))
n=1000
print(n)
for i in range(n):
print(randcmd())
%Makefile
all: cmp
regen:
del rand.in
make all
cmp: a.out o.out
diff a.out o.out
a.out: rand.in a.exe
a < rand.in > a.out 2> nul
o.out: rand.in o.exe
o < rand.in > o.out 2> nul
a.exe: main.cpp
cc main.cpp -o a
o.exe: others.cpp
cc others.cpp -o o
rand.in: datagen.py
python datagen.py > rand.in
clean:
del *.exe rand.in a.out o.out
n=10
整了好几次,就是那个一改就超时的地方,我怎么都想不出来哪里有死循环.
结果
直到我把n改成1000,结果好久都不出结果.
所以我终于知道了,是把时间浪费在IO上了.
于是我把那个函数tree
去掉,结果就过了.
最后,
#include <bits/stdc++.h>
#define contains(a,b) ((a)->v.infoD.ch->find(b)!=(a)->v.infoD.ch->end())
#define get(a,b) ((*(a)->v.infoD.ch)[b])
using namespace std;
typedef long long ll;
struct File{
enum{
D,F}type;
union{
struct{
ll ld,lr;
ll sd,sr;
string *name;
map<string,File*> *ch;
}infoD;
struct{
ll size;
string *name;
}infoF;
}v;
};
File *newDir(const string& name) {
return new File({
File::D,
{
{
0,0,0,0,
new string(name),
new map<string,File*>}}
});
}
File *newFile(ll size,const string& name) {
File *ret=new File;
ret->type=File::F;
ret->v.infoF.size=size;
ret->v.infoF.name=new string(name);
return ret;
}
File *fs=newDir("");
void tree(File *cur=fs,int n=0) {
return;
if(cur->type==File::F)cerr<<'F';
else cerr<<'D';
for(int i=0;i<n;++i)cerr<<'\t';
if(cur->type==File::F){
cerr<<*(cur->v.infoF.name)<<' '<<cur->v.infoF.size<<endl;
}
else{
cerr<<*(cur->v.infoD.name)<<' '<<cur->v.infoD.sd<<' '<<cur->v.infoD.sr<<' '<<cur->v.infoD.ld<<' '<<cur->v.infoD.lr<<endl;
for(auto i:*cur->v.infoD.ch){
tree(i.second,n+1);
}
}
}
vector<string> dirs;
string name;
void split(const string& path){
dirs.clear();
char buf[101];
int i=1,j=0;
for(;i<path.size();++i){
if(path[i]=='/'){
buf[j]=0;
j=0;
dirs.push_back(buf);
}
else{
buf[j++]=path[i];
}
}
buf[j]=0;
name=buf;
}
enum State{
Filemet,Ffalse,Found,Notfound};
State tranverse(File *&cur,function<bool(File*,const string&)> f) {
cur=fs;
for(int i=0;i<dirs.size();++i){
if(!f(cur,dirs[i]))return Ffalse;
if(!contains(cur,dirs[i]))return Notfound;
cur=get(cur,dirs[i]);
if(cur->type==File::F)return Filemet;
}
return Found;
}
bool create(){
string path;
ll size,fsize=0;
cin>>path>>size;
split(path);
File *cur=fs,*t,*tar;
State st=tranverse(cur,[&](File *cur,const string& s)->bool{
return true;
});
if(st==Filemet){
cerr<<"can't create dir with the name same with file"<<endl;return false;}
if(st==Found&&contains(cur,name)){
tar=get(cur,name);
if(tar->type==File::D){
cerr<<"can't create file with the name same with dir"<<endl;return false;}
else fsize=tar->v.infoF.size;
}
tranverse(cur,[&](File *cur,const string& s)->bool{
if(cur->v.infoD.lr!=0&&cur->v.infoD.sr-fsize+size>cur->v.infoD.lr){
cerr<<"lr exceeded"<<endl;return false;}//this ocationally right
if(!contains(cur,s)){
t=newDir(s);
get(cur,s)=t;
}
return true;
});
if(cur->v.infoD.lr!=0&&cur->v.infoD.sr-fsize+size>cur->v.infoD.lr){
cerr<<"lr exceeded"<<endl;return false;}
if(cur->v.infoD.ld!=0&&cur->v.infoD.sd-fsize+size>cur->v.infoD.ld){
cerr<<"ld exceeded"<<endl;return false;}
tranverse(cur,[&](File *cur,const string& s)->bool{
cur->v.infoD.sr+=-fsize+size;
return true;
});
cur->v.infoD.sr+=-fsize+size;
cur->v.infoD.sd+=-fsize+size;
t=newFile(size,name);
get(cur,name)=t;//memory leaking? never mind.
return true;
}
bool remove(){
string path;
cin>>path;
ll fsize=0;
split(path);
File *cur=fs,*tar;
State st=tranverse(cur,[&](File *cur,const string& s)->bool{
return true;
});
if(st==Notfound||st==Filemet)return true;
if(contains(cur,name)){
tar=get(cur,name);
if(tar->type==File::D)fsize=tar->v.infoD.sr;
else fsize=tar->v.infoF.size;
}
else return true;
cur=fs;
tranverse(cur,[&](File *cur,const string&)->bool{
cur->v.infoD.sr+=-fsize;
return true;
});
if(tar->type==File::F)cur->v.infoD.sd+=-fsize;
cur->v.infoD.sr+=-fsize;
cur->v.infoD.ch->erase(name);//memory leaking. never mind.
return true;
}
bool query(){
//?
string path;
ll ld,lr;
File *cur=fs,*tar;
cin>>path>>ld>>lr;
split(path);
State st=tranverse(cur,[&](File *cur,const string&)->bool{
return true;
});
if(st==Notfound||st==Filemet)return false;
if(contains(cur,name)){
tar=get(cur,name);
if(tar->type==File::F){
cerr<<"not a directory"<<endl;return false;}
}
else if(cur==fs&&name=="")tar=fs;
else {
cerr<<"file not found"<<endl;return false;}
if(lr!=0&&tar->v.infoD.sr>lr){
cerr<<"lr exceeded"<<endl;return false;}
if(ld!=0&&tar->v.infoD.sd>ld){
cerr<<"ld exceeded"<<endl;return false;}
tar->v.infoD.lr=lr;
tar->v.infoD.ld=ld;
return true;
}
int main(){
//freopen("test3.in","r",stdin);
int n;
char c;
cin>>n;
bool state;
for(int i=0;i<n;++i){
cin>>c;
cerr<<i<<"----------------"<<c<<endl;
switch(c){
case 'C':
state=create();break;
case 'R':
state=remove();break;
case 'Q':
state=query();break;
}
cout<<(state?'Y':'N')<<endl;
tree();
}
return 0;
}