这周三就要去机试,我赶紧做了一下往年的题目,牛客上只找到一篇,所以赶紧写了一下,一看,看来明天是凉凉了,下面开始三题的注解,主要的思路见注释。
(在看到精炼完美的代码时,发现他们经常会用到vector,string,algorithm库,所以想在题解完毕之后对那些经常用到的简单地总结一下)
第一题
#include <iostream> #include <stdio.h> #include <vector> using namespace std; int main() { int N = 0, M = 0;//第一个为人数,第二个更新的次数 int score[30001] = {0};//题目讲明不超过30000 int tempMaxScore = 0;//最高分 int nIndex = 0;//下标 int A = 0,B = 0;//修改内容 char chMode = 0;//修改符 //除n,m外的变量,都可以放入while循环里面 while (cin >> N >> M)//多组数据测试,故用while循环 { nIndex = 1; while(N--) { cin >> score[nIndex];//将成绩全部存到score数组 nIndex++; } while(M--) { cin >> chMode >> A >> B; if(chMode == 'Q')//表示查询 { int start = (A < B) ? A:B; int end = (A < B) ? B:A;//这两步保证了a<b tempMaxScore = 0;//相当于哨兵,依次比较 for(nIndex = start; nIndex <= end; nIndex++)//找出a到b之间的最大值 { if(score[nIndex] > tempMaxScore ) { tempMaxScore = score[nIndex]; } } cout << tempMaxScore << endl; } else if(chMode == 'U')//更新操作 { score[A] = B; } } } return 0; }
其实上述代码有点麻烦,而且可读性差,我看见另一位大佬写的代码简洁有效,下面给出一个较好的答案:
#include<algorithm>//算法库(之后会有小小的总结) #include<vector>//容器库 #include<iostream> using namespace std; int main() { int N,M; while(cin>>N>>M) { vector<int> stu(N);//首先创建int容器保存分数 int a,b;char c;//修改符和修改值 for(int i=0;i<N;++i) { cin>>stu[i];//把成绩保存到容里 } for(int j=0;j<M;++j) { cin>>c>>a>>b; if(c=='Q') { if(a>b)swap(a,b);//属于算法库里的函数,交换函数 cout<<*max_element(stu.begin()+a-1,stu.begin()+b)<<endl; //属于算法库里函数,返回的时迭代器,所以加上取内容符号,另外范围是左开右闭,即[a,b),所以一个是a-1,一个是b.(注意下标从0开始) } if(c=='U') { stu[a-1]=b; } } } return 0; }
一目了然啊,代码赏心悦目,直接用swap()函数交换,用max_element()函数返回容器里最大值的迭代器,思路清晰。
第二题
#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; bool compare(pair<string, int> a, pair<string, int> b) //将输入分为路径和后面的数字(行数),这个函数表示返回数字大的; //注意到,pair 中有两个值 一个是first另一个是second { return a.second > b.second; } int main() { string input, file;//一个是输入,一个是将截断输入获取文件名 vector<pair<string, int>> errors;//一个基本类型为pair的容器 while (getline(cin, input))//多次输入用while { if (input.size() == 0) { break; } unsigned int f = input.rfind('\\');//从右往左寻找\,注意到多一个\表示转义 file = input.substr(f + 1);//于是输入从右往左第一个\后面的就是文件名 errors.push_back(make_pair(file, 1));//将其放入容器并编号1 for (int i = 0; i<(errors.size() - 1); i++) { if (errors[i].first == file)//检查是否重名,若重名,将数目加一并删除一个相同的 { errors[i].second++; errors.pop_back(); break; } } } stable_sort(errors.begin(), errors.end(), compare);//按second大小排序,并且stable_sort是稳定排序 int idx = 0; while (idx<8 && idx<errors.size())//最多8个 { string check = errors[idx].first; int t = check.find(' ');//空格前面的即文件名 if (t>16)//文件名称不超过16 { errors[idx].first.erase(0, t - 16); } cout << errors[idx].first << ' ' << errors[idx].second << endl; idx++; } }
该代码中仍有很多库函数,使代码变得简洁,思路清晰。
第三题
#include<iostream> #include<string> #include<algorithm> using namespace std; int main() { string s; while(getline(cin,s))//多个测试用例,用while循环 { if(s.find("joker JOKER")!=-1)//find()函数,有大小王,则大小王最大。find()函数找不到则返回-1,否则返回指向该元素的迭代器 { cout<<"joker JOKER"<<endl; } else { int temp=s.find('-');//找到分割符,使其分为两部分 string s1=s.substr(0,temp);//第一部分 string s2=s.substr(temp+1);//第二部分 int c1=count(s1.begin(),s1.end(),' ');//count()函数,计算[]之间空格个数,这就间接知道了字符个数了 int c2=count(s2.begin(),s2.end(),' ');//第二部分的字符个数 string a1=s1.substr(0,s1.find(' '));//第一部分第一个数 string a2=s2.substr(0,s2.find(' ')); string str="345678910JQKA2jokerJOKER"; if(c1==c2) { if(str.find(a1)>str.find(a2))//长度一样,只需比较第一个数即可,无论是对子,炸弹,顺子 { cout<<s1<<endl; } else { cout<<s2<<endl; } } else if(c1==3)//三张牌 只能跟同类比较或炸弹,长度不一样,跟炸弹比,很显然比炸弹小 { cout<<s1<<endl; } else if(c2==3)//同理 { cout<<s2<<endl; } else//只能同类型比较(或炸弹),其他情况讨论可知都是错误的 { cout<<"ERROR"<<endl; } } } }
暂且这样,将在下一篇博客简单总结 “容器,迭代器,算法”,再见,朋友们!