Leetcode刷题笔记25:202012-1-2-3(CSP考试经验 | 深入理解C++迭代器 | C++字符串分割)

第二十一天 2021-4-4 备战CSP
刷题模块:CSP 202012-1-2-3-4
CSP考试经验:
1. #include<bits/stdc++.h>包含全部头文件;
2. 使用全局变量;
3. O(1)的参数都定义为long long类型;
4. 使用加速输入语法cin.tie()和sync_with_stdio(); !!!输入字符串请勿使用
5. 面对较难的算法,画一下整个算法流程;
6. 注意输入类型和定义类型一致。

一、202012-1

无难点,一遍过

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll score,w;
ll y;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	y=0;
	cin>>n;
	while(n--){
		cin>>w>>score;
		y=y+(w*score);
	}
	
	if(y>0) cout<<y;
	else cout<<0;
	
	return 0;
} 

二、202012-2

O(n^2)的暴力搜索只有70分,会导致TLE。

参考满分解答思路:期末预测之安全指数(202012-2/CCF)———附带思路和完整代码
后自己独立完成。

这道题debug了两个多小时,原因一是在于没有根本理解迭代器,详情见下一节。
二是没有在意类型定义,定义为long long,却在输入时传入int导致错位

满分代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10005;

struct Person{
	int true_count,false_count;
	int tsum,fsum;
	Person():true_count(0),false_count(0),tsum(0),fsum(0){}
};
int m;
int score,result;
int maxSum,maxScore;
int sumTrue;
map<int,Person> stat;

int main(){
	//get input and initalize the stat
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		scanf("%d%d",&score,&result);
		if(result) stat[score].true_count++;
		else stat[score].false_count++;
	}
	
	//calculate the cumulative sum
	auto beit=stat.begin();
	auto it=stat.begin();
	beit->second.tsum=0;
	beit->second.fsum=0;
	for(it++;it!=stat.end();it++,beit++){
		it->second.tsum=(beit)->second.tsum+(beit)->second.true_count;
		it->second.fsum=(beit)->second.fsum+(beit)->second.false_count;
	}
	sumTrue=stat.rbegin()->second.tsum+stat.rbegin()->second.true_count;

	//calculate the result
	maxSum=0;
	int tmpSum;
	for(it=stat.begin();it!=stat.end();it++){
		tmpSum = it->second.fsum + sumTrue - it->second.tsum;
		if(tmpSum>=maxSum){
			maxSum=tmpSum;
			maxScore=it->first;
		}
	}
	
	//return the result
	printf("%d\n",maxScore);
	
	return 0;
}

三、深入理解C++迭代器

直接进行代码讲解

#include<bits/stdc++.h>
using namespace std;

map<int,int> stat{{0,10},{1,11},{2,12},{3,13},{4,14},{5,15}};

int main(){
	//返回指向第一个元素的指针 
	auto it=stat.begin();
	printf("key:%d value:%d\n",it->first,it->second);
	puts("");
	
	//迭代器向后移动
	it++;
	it++;
	printf("key:%d value:%d\n",it->first,it->second);
	it--;
	printf("key:%d value:%d\n",it->first,it->second); 
	//it+1;it-1; 此类操作均报错,迭代器只支持++或--向后或向前移动
	puts("");
	
	//注意迭代器的复制 
	auto newit=--it;
	printf("newit\tkey:%d value:%d\n",newit->first,newit->second);
	printf("it\t   key:%d value:%d\n",it->first,it->second);
	/*使用此操作获得it的前一个值,但是it本身也会移动,而又因为不支持+和-运算
	因此最好先=后,再将需要的迭代器使用++或--移动*/ 
	
	return 0;
}

在这里插入图片描述

四、C++字符串分割

String方法讲解

在C++ string类中,提供了两个成员函数可以用来实现字符串分割,一个是find函数,另一个是substr函数,下面看一下这两个函数的声明。

find函数:

原型size_t find (const string& str, size_t pos = 0) const;
功能:查找子字符串第一次出现的位置。
参数说明:str为子字符串,pos为初始查找位置。
返回值:找到的话返回第一次出现的位置,否则返回string::npos

substr函数:

原型:** string substr (size_t pos = 0, size_t len = npos) const;**
功能:在原字符串中截取子字符串。
参数说明:pos为起始位置,len为要截取子字符串的长度。
返回值:子字符串。

vector<string> split(const string &str, const string &pattern)
{
    vector<string> res;
    if(str == "")
        return res;
    //在字符串末尾也加入分隔符,方便截取最后一段
    string strs = str + pattern;
    size_t pos = strs.find(pattern);

    while(pos != strs.npos)
    {
        string temp = strs.substr(0, pos);
        res.push_back(temp);
        //去掉已分割的字符串,在剩下的字符串中进行分割
        strs = strs.substr(pos+1, strs.size());
        pos = strs.find(pattern);
    }

    return res;
}

五、202012-3

文件系统模拟
写了将近8个小时,终于调试通并通过测试案例
OJ只给了20分,但是没有继续Debug的精力了。

#include<bits/stdc++.h>
#include<stdio.h>
using std::cin;
using std::cout;
using std::string;
using std::map;
using std::min;
typedef long long ll;

const int N=100005;

struct Dirc{
	map<string,ll>    files;	//storge files;
	map<string,Dirc*> dircs; 	//storge dirs;
	Dirc* parent;
	ll _ld,_lr;					//storge setting
	ll ld,lr;					//storge condition
	Dirc():ld(0),lr(0),_ld(LLONG_MAX),_lr(LLONG_MAX),parent(nullptr){
		files.clear();
		dircs.clear();
	}
	Dirc(Dirc* parent):ld(0),lr(0),_ld(LLONG_MAX),_lr(LLONG_MAX),parent(parent){
		files.clear();
		dircs.clear();
	}
};
int n;
char op;
string path;
ll size,_ld,_lr;
Dirc* root=new Dirc();

string split(string& str){
	size_t pos=str.find("/");
	string res="";
	if(pos!=string::npos){
		res=str.substr(0,pos);
		str=str.substr(pos+1,str.size());
	}
	return res;
}

void updateQuota(Dirc* node,ll difSize){
	while(node!=nullptr){
		node->lr+=difSize;
		if(node->_lr < node->lr) printf("Error\n");
		node=node->parent;
	}
}

bool createFile(Dirc* node,ll dif){
	string name=split(path);
	
	if(path!=""){														//name is a dirc
		if(node->files.count(name)) return false;			//duplication name
		else{												//decline deep
			if(node->dircs.count(name)==0){			//create a new dirc
				Dirc* newNode=new Dirc(node);
				node->dircs[name]=newNode;
			}
			//kernel:pass the min lr
			ll minDif = min(node->_lr-node->lr,dif);
			return createFile(node->dircs[name],minDif);
		}
	}
	else{																//name is a file
		//is conflict with the file name
		if(node->dircs.count(name)) return false;
		//is File exist?
		ll difSize = node->files.count(name) ? size - node->files[name] : size;
		if(!node->files.count(name)) node->files[name]=size;
		//is create legal?
		dif=min(dif,node->_lr-node->lr);
		if((difSize<=dif) && (node->_ld - node->ld > difSize)){
			node->ld += difSize;
			updateQuota(node,difSize);
			return true;
		}
		else return false;
	}
}

void removeFile(Dirc* node){
	string name=split(path);
	
	//Special judgment of the root directory
	if(name==""){
		root->lr=0;
		root->ld=0;
		root->dircs.clear();
		root->files.clear();
	}
	
	if(path!=""){
		if(!node->dircs.count(name)) return;
		else{
			removeFile(node->dircs[name]);
			return;
		}
	}
	else{
		ll difSize;
		if(node->files.count(name)){				//delete file
			difSize=-(node->files[name]);
			node->ld-=difSize;
			node->lr-=difSize;
			node->files.erase(name);
		}
		else if(node->dircs.count(name)){			//delete dirc	
			difSize=-(node->dircs[name]->lr);
			node->lr-=difSize;
			node->dircs.erase(name);
		}
		else return;
		updateQuota(node,difSize);
	}
}

bool setQuota(Dirc* node){
	string name=split(path);
	
	//Special judgment of the root directory
	if(name==""){
		if((_ld!=0 && node->ld>_ld) ||  (_lr!=0 && node->lr>_lr)) return false; 
		else{
			if(_ld!=0) node->_ld=_ld;
			if(_lr!=0) node->_lr=_lr;
			return true;
		}
	}
	
	if(node->dircs.count(name)==0) return false;
	if(path!="") return setQuota(node->dircs[name]);
	else{
		node=node->dircs[name];
		if((_ld!=0 && node->ld>_ld) ||  (_lr!=0 && node->lr>_lr)) return false; 
		else{
			if(_ld!=0) node->_ld=_ld;
			if(_lr!=0) node->_lr=_lr;
			return true;
		}
	}
}

int main(){
	freopen("in.txt","r",stdin);
	
	scanf("%d",&n);
	while(n--){
		cin>>op>>path;
		path=path+"/";
		path=path.substr(1,path.size());
		
		if(op=='C'){
			scanf("%lld",&size);
			if(createFile(root,LLONG_MAX)) printf("Y\n");
			else printf("N\n");
		}
		else if(op=='R'){
			removeFile(root);
			printf("Y\n");			
		}
		else{
			scanf("%lld%lld",&_ld,&_lr);
			if(setQuota(root)) printf("Y\n");
			else printf("N\n");
		}
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值