带配额的文件系统csp

1.解题思路

感觉算是csp第三题中比较复杂的情况了,插入需考虑文件路径是否存在,不存在且其双亲文件下无同名的普通文件才能创建新文件,存在但为目录文件执行失败,执行失败都要进行回溯删除之前的插入操作,存在且为普通文件且满足配额要求的可以进行替换同时更新配额值,删除需考虑文件不存在和文件是目录/普通文件的情况并进行相应配额值的更新,配额需考虑路径不存在、非目录文件以及能否进行配额替换等情况。

详细思路请见代码注释

2.满分代码

#include<iostream>
#include<string.h>
#include<vector>
#include<map>
#include<utility>
using namespace std;
typedef long long ll;
const int N=5e6+6;
struct file{
	map<string,int>child;//孩子文件名--孩子节点编号 
	int type;//0--目录  1--文件 
	ll size;//大小 
	ll LD,LR;//孩子 后代配额 
	ll ld,lr;//孩子文件/后代文件所占大小 
	int father;//双亲节点编号 
}tr[N];
int n;
string getname(string str,int &num)//以/为分隔符 提取每一层文件名 
{
	string res="";
	int len=str.size();
	int i;
	for(i=num;str[i]!='/'&&i<len;i++)
	{
		res+=str[i];
	}
	num=i+1;
	return res;
} 
vector<pair<int,string>>v;//文件编号--文件名 
int vex;
void del()//插入失败时删除 
{
	for(int i=0;i<v.size();i++)
	{
		int index=v[i].first;
		string fname=v[i].second;
		tr[index].child.erase(tr[index].child.find(fname));
	}
}
bool insert(string s,ll size)//插入 
{
	v.clear();
	int back=vex,num=1,fa=0,len=s.size();
	while(num<len)
	{
		string fname=getname(s,num);
		if(tr[fa].child[fname]&&tr[tr[fa].child[fname]].type&&num<len)//存在与该目录同名的普通文件 
		{
			vex=back;
			del();
			return false;
		}
		int id,flag=0;
		if(tr[fa].child[fname])//该文件已存在 
		{
			id=tr[fa].child[fname];
			flag=1;
		}
		else//不存在则创建 
		{
			id=++vex;
			tr[id].type=0;
			tr[id].father=fa;
			tr[id].LD=tr[id].LR=0;
			tr[fa].child[fname]=id;
			v.push_back(make_pair(fa,fname));
		}
		if(num<len)
		fa=id;
		if(num>=len)//到达叶子节点 
		{
			ll addsize=0;
			if(flag)//文件存在 
			{
				if(!tr[id].type)//是目录文件 
				{
					vex=back;
					del();
					return false;
				}
				addsize=size-tr[id].size;
			}
			else
			addsize=size;
			if(addsize+tr[fa].ld>tr[fa].LD&&tr[fa].LD)//该文件不满足双亲文件的孩子配额要求 
			{
				vex=back;
				del();
				return false;
			}
			tr[id].size=size;
			tr[id].type=1;
			tr[id].lr=size;
			for(int i=fa;i!=-1;i=tr[i].father)//该文件是否满足其双亲及祖先文件的后代配额要求 
			{
				if(tr[i].lr+addsize>tr[i].LR&&tr[i].LR)
				{
					vex=back;
					del();
					return false;
				}
			}
			for(int i=fa;i!=-1;i=tr[i].father)//更新 
			{
				tr[i].lr+=addsize;
			}
			tr[fa].ld+=addsize;
		}
	}
	return true;
}
void remove(string s)//移除 
{
	int fa=0;
	int num=1;
	int len=s.size();
	while(num<len)
	{
		string fname=getname(s,num);
		if(tr[fa].child.find(fname)==tr[fa].child.end())return;//文件路径不存在 
		int id=tr[fa].child[fname];
		if(num<len)
		fa=id;
		if(num<len&&tr[id].type)return;//不合法的路径 
		if(num>=len)//到达叶子节点 
		{
			tr[fa].child.erase(tr[fa].child.find(fname));//删除该文件 
			for(int i=fa;i!=-1;i=tr[i].father)//更新该文件的双亲及祖先文件 的lr值 
			{
				tr[i].lr-=tr[id].lr;
			}
			if(tr[id].type)//若该文件为普通文件 还需更新该文件双亲文件的ld值 
			tr[fa].ld-=tr[id].lr;
		} 
	}
}
bool config(string s,ll LD,ll LR)//配置 
{
	if(s.size()==1)//配置根目录 
	{
		int id=0;
		if((LD<tr[id].ld&&LD)||(LR<tr[id].lr&&LR))return false;//孩子配额或后代配额不满足要求 
		tr[id].LD=LD;
		tr[id].LR=LR;
		return true; 
	}
	int num=1,fa=0;
	int len=s.size();
	while(num<len)
	{
		string fname=getname(s,num);
		if(tr[fa].child.find(fname)==tr[fa].child.end())return false;//文件路径不存在 
		int id=tr[fa].child[fname];
		fa=id;
		if(tr[id].type)return false;//为普通文件 
		if(num>=len)
		{
			if((LD<tr[id].ld&&LD)||(LR<tr[id].lr&&LR))return false;//不满足配额要求 
			tr[id].LD=LD;
			tr[id].LR=LR;
			return true;
		}
	} 
}
int main()
{
	cin>>n;
	tr[0].type=0;
	tr[0].LD=tr[0].LR=tr[0].ld=tr[0].lr=0;
	tr[0].father=-1;
	while(n--)
	{
		char c;
		cin>>c;
		int flag=1;
		if(c=='C')
		{
			string path;
			int fsize;
			cin>>path>>fsize;
			flag=insert(path,fsize);
		}
		else if(c=='R')
		{
			string path;
			cin>>path;
			remove(path);
		}
		else if(c=='Q')
		{
			string path;
			ll LD,LR;
			cin>>path>>LD>>LR;
			flag=config(path,LD,LR);
		}
		if(flag)cout<<"Y"<<endl;
		else cout<<"N"<<endl;
	}
	return 0;
} 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值