第二十一天 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++字符串分割
在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;
}