您的位置:首页 > 编程语言 > C语言/C++

2017 程序设计实习之C++部分作业题汇总 - H:STL 容器与算法

2017-05-10 12:19 776 查看
题目来源:2017 程序设计实习之C++部分作业题汇总

1、H01:List

总时间限制: 4000ms 内存限制: 65536kB

描述

写一个程序完成以下命令:

new id ——新建一个指定编号为id的序列(id<10000)

add id num——向编号为id的序列加入整数num

merge id1 id2——合并序列id1和id2中的数,并将id2清空

unique id——去掉序列id中重复的元素

out id ——从小到大输出编号为id的序列中的元素,以空格隔开

输入

第一行一个数n,表示有多少个命令( n<=200000)。以后n行每行一个命令。

输出

按题目要求输出。

样例输入

16

new 1

new 2

add 1 1

add 1 2

add 1 3

add 2 1

add 2 2

add 2 3

add 2 4

out 1

out 2

merge 1 2

out 1

out 2

unique 1

out 1

样例输出

1 2 3

1 2 3 4

1 1 2 2 3 3 4

1 2 3 4

code for List

#include <iostream>
#include <algorithm>
#include <string>
#include <list>
using namespace std;
list<int> lst[10005];
template<class T>
void Print(T b,T e)
{
while (b != e)
cout << *b++ << " ";
cout << endl;
}
int main()
{
int n, id, id_1, id_2, num;
cin >> n;
string s;

while (n--)
{
cin >> s;
if (s == "new") {   cin >> id; }
else if (s == "add") {
cin >> id >> num;
lst[id].push_back(num);
}
else if (s == "out") {
cin >> id;
lst[id].sort();
Print(lst[id].begin(), lst[id].end());
}
else if (s == "merge") {
cin >> id_1 >> id_2;
lst[id_1].merge(lst[id_2]);
}
else if (s == "unique") {
cin >> id;
lst[id].sort();
lst[id].unique();
}
}
return 0;
}


2、H02:RPN Calculator

总时间限制: 1000ms 内存限制: 10000kB

描述

Reverse Polish notation (or just RPN) by analogy with the related Polish notation, a prefix notation introduced in 1920 by the Polish mathematician Jan Łukasiewicz, is a mathematical notation wherein every operator follows all of its operands. It is also known as Postfix notation.

In Reverse Polish notation the operators follow their operands; for instance, to add three and four one would write “3 4 +” rather than “3 + 4”. If there are multiple operations, the operator is given immediately after its second operand; so the expression written “3 − 4 + 5” in conventional infix notation would be written “3 4 − 5 +” in RPN: first subtract 4 from 3, then add 5 to that. An advantage of RPN is that it obviates the need for parentheses that are required by infix. While “3 − 4 * 5” can also be written “3 − (4 * 5)”, that means something quite different from “(3 − 4) * 5”, and only the parentheses disambiguate the two meanings. In postfix, the former would be written “3 4 5 * −”, which unambiguously means “3 (4 5 *) −”.

You were asked to design a simple RPN calculator, which will support the “+”, “-“, “*”, “/”(the absolute value of the divisor will not less then 10^-9) and “^”(power operator, if the base number b<=0, the exponential e must be a positive integer not greater than 10^9) operators. You can assume all the numbers during the calculation can fit into a double-precision floating point number.

In addition, our calculator has some memory. Each time we calculate an expression, the smallest number in the memory will be erased, and replace it with the value of the expression.

输入

The first line contains an integer n, which is the memory size of our calculator.

From the second line, we will give n numbers, which is the initial value of the memory. each line except last will have 10 numbers.

And then each line has a valid RPN expression we previously described, end with “=”, which is the command for calculation. Each term will no longer than 20 characters.

输出

For each expression, output the value of it in a line.

And then output an empty line to separate the two parts.

At last, output the all the numbers in memory, in increasing order, 10 numbers per line.

Each number should be formatted in scientific notation with 6 digits after decimal point and 2 digits of exponential, such like “%e” format string of printf() function in C. The numbers in a line should be separated by a space.

样例输入

4

1e6 1e-6 0.001 1000

1 2 + 3 4 + * =

1 0.1 / 8 ^ =

样例输出

2.100000e+01

1.000000e+08

2.100000e+01 1.000000e+03 1.000000e+06 1.000000e+08

提示

Huge input, scanf() is recommended

%e格式输出在windows环境下指数部分为3位,在系统的测试环境下为2位。

code for RPN Calculator

#include <iostream>
#include <cstdlib>
#include <string>
#include <stack>
#include <cmath>
#include <set>
using namespace std;
int main()
{
int n;
cin >> n;
double num;
string s;
multiset<double> mst;
multiset<double> ::iterator aim;
stack<double> st;
for (int i = 1; i <= n; ++i)
{
cin >> num;
mst.insert(num);
}
double x, y, re;
// calculate the value of each expression
while (cin >> s)
{
if (s == "+" || s == "-" || s == "*" || s == "/" || s == "^")
{
x = st.top();   st.pop();
y = st.top();   st.pop();
if (s == "+")   re = y + x;
else if (s == "-")  re = y - x;
else if (s == "*")  re = y * x;
else if (s == "/")  re = y / x;
else if (s == "^")  re = pow(y,x);
st.push(re);
}
else if (s == "=")
{
re = st.top();  st.pop();
printf("%e\n", re);
aim = mst.begin();
//Ref the description:
//delete the least element in the memory first
//then add the cur value of the exp into the memory
mst.erase(aim);
mst.insert(re);
}
else
st.push(atof(s.c_str()));
}
//output the memory in the requsted order and format
printf("\n");
int k = 1;
aim = mst.begin();
while (aim != mst.end())
{
if (k % 10 == 0)
printf("%e\n", *aim++);
else
printf("%e ", *aim++);
++k;
}
printf("\n");
return 0;
}


3、H03:Set

总时间限制: 5000ms 内存限制: 100000kB

描述

现有一整数集(允许有重复元素),初始为空。我们定义如下操作:

add x 把x加入集合

del x 把集合中所有与x相等的元素删除

ask x 对集合中元素x的情况询问

对每种操作,我们要求进行如下输出。

add 输出操作后集合中x的个数

del 输出操作前集合中x的个数

ask 先输出0或1表示x是否曾被加入集合(0表示不曾加入),再输出当前集合中x的个数,中间用空格格开。

输入

第一行是一个整数n,表示命令数。0<=n<=100000。

后面n行命令,如Description中所述。

输出

共n行,每行按要求输出。

样例输入

7

add 1

add 1

ask 1

ask 2

del 2

del 1

ask 1

样例输出

1

2

1 2

0 0

0

2

1 0

提示

Please use STL’s set and multiset to finish the task

code for Set

#include <iostream>
#include <algorithm>
#include <string>
#include <set>
using namespace std;
int main()
{
int n, num;
cin >> n;
string s;
multiset<int> mst;
multiset<int> mst_copy;
while (n--)
{
cin >> s >> num;
if (s == "ask") {
multiset<int>::iterator pos = mst_copy.find(num);
if (pos != mst_copy.end())
cout << 1 << " " << mst.count(num) << endl;
else
cout << 0 << " " << mst.count(num) << endl;
}
else if (s == "add") {
mst.insert(num);
mst_copy.insert(num);
cout << mst.count(num) << endl;
}
else if (s == "del") {
cout << mst.count(num) << endl;
pair<multiset<int>::iterator, multiset<int>::iterator> p = mst.equal_range(num);
mst.erase(p.first, p.second);
}
}
return 0;
}


4、H04:字符串操作

总时间限制: 1000ms 内存限制: 65536kB

描述

给定n个字符串(从1开始编号),每个字符串中的字符位置从0开始编号,长度为1-500,现有如下若干操作:

copy N X L:取出第N个字符串第X个字符开始的长度为L的字符串。

add S1 S2:判断S1,S2是否为0-99999之间的整数,若是则将其转化为整数做加法,若不是,则作字符串加法,返回的值为一字符串。

find S N:在第N个字符串中从左开始找寻S字符串,返回其第一次出现的位置,若没有找到,返回字符串的长度。

rfind S N:在第N个字符串中从右开始找寻S字符串,返回其第一次出现的位置,若没有找到,返回字符串的长度。

insert S N X:在第N个字符串的第X个字符位置中插入S字符串。

reset S N:将第N个字符串变为S。

print N:打印输出第N个字符串。

printall:打印输出所有字符串。

over:结束操作。

其中N,X,L可由find与rfind操作表达式构成,S,S1,S2可由copy与add操作表达式构成。

输入

第一行为一个整数n(n在1-20之间)

接下来n行为n个字符串,字符串不包含空格及操作命令等。

接下来若干行为一系列操作,直到over结束。

输出

根据操作提示输出对应字符串。

样例输入

3

329strjvc

Opadfk48

Ifjoqwoqejr

insert copy 1 find 2 1 2 2 2

print 2

reset add copy 1 find 3 1 3 copy 2 find 2 2 2 3

print 3

insert a 3 2

printall

over

样例输出

Op29adfk48

358

329strjvc

Op29adfk48

35a8

提示

推荐使用string类中的相关操作函数。

code for 字符串操作

NOTE:

Status:Accepted

Memory used:136kB

Time used:2ms

Lenth of code:4241 B 代码有些长,AC的最短的是1600B左右,大部分在3000B左右

Important:

1、add是一个重点,需要判断S1,S2是否为0-99999之间的整数

2、根据描述,N,X,L可由find与rfind操作表达式构成,S,S1,S2可由copy与add操作表达式构成,所以这四个方法需要有相应的返回值

3、以insert copy 1 find 2 1 2 2 2为例分析处理逻辑,若正向考虑,需要后续表达式的值。反向计算则可以根据全部的参数得到完整的结果

故用主栈major分离命令的每一项,全部入栈之后开始出栈:

出栈的不是cmd,那一定是作为某个cmd的参数,入副栈junior

若是cmd,根据cmd需要参数的个数,在副栈junior中取出需要的项

根据cmd,如cmd有返回值,返回值又是左边的下一个cmd的参数,入副栈junior,若cmd没有返回值,则不需要对junior操作

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <stack>
using namespace std;
class Mystring
{
public:
string input[25];
string str;
string cmd;
int len;
stack<string> major;
stack<string> junior;
int pos;
public:
Mystring();
void work();
void seperate();
void redeal();
string copy(int id, int pos, int len);
string add(const string &s1, const string &s2);
int find(const string &s, int id);
int rfind(const string &s, int id);
void insert(const string & s, int id, int pos);
void reset(const string & s, int id);
void print(int id);
void printall();
void over();
bool test(const string & s);
string convert(int n);
};
//构造函数,读入n个str
Mystring::Mystring()
{
cin >> len;
for (int i = 1; i <= len; ++i)
cin >> input[i];
}

void Mystring::work()
{
while (getline(cin, str))
{
seperate();//用栈major分离每一条命令中的每一项,处理完毕之后已经逆序
redeal();//处理major栈,处理的时候可以得到完整的参数
}
}

void Mystring::seperate()
{
while (str.length() > 0)
{
pos = str.find(' ');
if (pos != string::npos)
{
cmd = str.substr(0, pos);
str = str.substr(pos + 1);
}
else
{
cmd = str;
str = "";
}
major.push(cmd);//get cmd and do something
}
}

void Mystring::redeal()
{
while (!major.empty())
{
string temp = major.top(); major.pop();//取出major的一项
//若temp是cmd,在副栈中取相应个参数;若不是,入副栈
if (temp == "copy")
{
int id = atoi((junior.top()).c_str());  junior.pop();
int pos = atoi((junior.top()).c_str()); junior.pop();
int lenth = atoi((junior.top()).c_str());   junior.pop();
junior.push(copy(id,pos, lenth));
}
else if (temp == "add")
{
string s1 = junior.top(); junior.pop();
string s2 = junior.top(); junior.pop();
junior.push(add(s1, s2));
}
else if (temp == "find")
{
string s = junior.top(); junior.pop();
int id = atoi((junior.top()).c_str());  junior.pop();
int re = find(s, id);
//find函数返回值int,需要将其转换为string,由convert函数实现
junior.push(convert(re));
}
else if (temp == "rfind")
{
string s = junior.top(); junior.pop();
int id = atoi((junior.top()).c_str());  junior.pop();
int re = rfind(s, id);
//rfind函数返回值int,需要将其转换为string,由convert函数实现
junior.push(convert(re));
}
else if (temp == "insert")
{
string s = junior.top(); junior.pop();
int id = atoi((junior.top()).c_str());  junior.pop();
int pos = atoi((junior.top()).c_str()); junior.pop();
insert(s, id, pos);
}
else if (temp == "reset")
{
string s = junior.top(); junior.pop();
int id = atoi((junior.top()).c_str());  junior.pop();
reset(s, id);
}
else if (temp == "print")
{
int id = atoi((junior.top()).c_str());  junior.pop();
print(id);
}
else if (temp == "printall")
{
printall();
}
else if (temp == "over")
{
over();
}
else
{
junior.push(temp);
}
}
}

string Mystring::copy(int id, int pos, int len)
{
return input[id].substr(pos, len);
}

string Mystring::add(const string & s1, const string & s2)
{
//可能会有完成判断的库函数,这里是自己实现的test判断0<=s<=99999的条件是否成立
if (test(s1) && test(s2))
{
int op1 = atoi(s1.c_str());
int op2 = atoi(s2.c_str());
int ans = op1 + op2;
return convert(ans);
}
else
return s1 + s2;
}

int Mystring::find(const string & s, int id)
{
int re = input[id].find(s);
if (re != string::npos)
return re;
else
return s.length();
}

int Mystring::rfind(const string & s, int id)
{
int re = input[id].rfind(s);
if (re != string::npos)
return re;
else
return s.length();
}

void Mystring::insert(const string & s, int id, int pos)
{
input[id].insert(pos, s);
}

void Mystring::reset(const string & s, int id)
{
input[id] = s;
}

void Mystring::print(int id)
{
cout << input[id] << endl;
}

void Mystring::printall()
{
for (int i = 1; i <= len; ++i)
cout << input[i] << endl;
}

void Mystring::over()
{
return;
}

string Mystring::convert(int n)
{
int mertrx[510];
string re = "";
if (n == 0)
{
re += '0';
return re;
}
else
{
int k = 0;
while (n > 0)
{
mertrx[k++] = n % 10;
n /= 10;
}
for (int i = k - 1; i >= 0; --i)
{
re += char(mertrx[i] + '0');
}
return re;
}
}
//test函数的功能,显然s.length()<6 && s.length()>0
//每一位都在指定返回之内才是符合条件的,否则不满足做整数加法的条件
bool Mystring::test(const string & s)
{
if(s.length()>=6 || s.length() == 0)
return false;
else
{
for (int i = 0; i < s.length(); ++i)
{
if ('0' <= s[i] && s[i] <= '9')
continue;
else
return false;
}
return true;
}
}

int main()
{
Mystring strop;
strop.work();
return 0;
}


5、H05:热血格斗场

总时间限制: 1000ms 内存限制: 65536kB

描述

为了迎接08年的奥运会,让大家更加了解各种格斗运动,facer新开了一家热血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。

我们假设格斗的实力可以用一个正整数表示,成为实力值。另外,每个人都有一个唯一的id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有两个人的实力值与他差别相同,则他会选择比他弱的那个(显然,虐人必被虐好)。

不幸的是,Facer一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮facer恢复比赛纪录,按照时间顺序依次输出每场比赛双方的id。

输入

第一行一个数n(0 < n <=100000),表示格斗场新来的会员数(不包括facer)。以后n行每一行两个数,按照入会的时间给出会员的id和实力值。一开始,facer就算是会员,id为1,实力值1000000000。输入保证两人的实力值不同。

输出

N行,每行两个数,为每场比赛双方的id,新手的id写在前面。

样例输入

3

2 1

3 3

4 2

样例输出

2 1

3 2

4 2

code for 热血格斗场

#include <iostream>
#include <map>
using namespace std;
template<class T>
struct Mycmp
{
bool operator()(const T & x, const T & y)
{
if (x.pow_ < y.pow_)
return true;
return false;
}

};
class  CMember
{
public:
int id_;
int pow_;
CMember(int i, int p) :id_(i), pow_(p) { ; }
};

int main()
{
map<CMember, int, Mycmp<CMember> > mmp;
map<CMember, int, Mycmp<CMember> >::iterator pos;
map<CMember, int, Mycmp<CMember> >::iterator aim;
map<CMember, int, Mycmp<CMember> >::iterator left_pos;
map<CMember, int, Mycmp<CMember> >::iterator right_pos;
mmp.insert(make_pair(CMember(1, 1000000000), -1));
int t;
int x, y;
cin >> t;
while (t--)
{
cin >> x >> y;
mmp.insert(make_pair(CMember(x, y), -1));
pos = mmp.find(CMember(x, y));
aim = left_pos = right_pos = pos;
if (pos == mmp.begin())
{
//被插入在了map的最开始的位置,pow最小,显然所求的id就是其后元素的id
pos->second = (++aim)->first.id_;
}
else if (pos == --mmp.end())
{
//被插入在了map的最后的位置,pow最大,显然所求的id就是其前元素的id
pos->second = (--aim)->first.id_;
}
else
{
//被插入在了map的中间的位置,需要与左右两边的元素比较,寻找左右差值较小的元素的id
//当差值相等时,左边的pow较小,所求的id就是其左元素的id
--left_pos; ++right_pos;
if (right_pos->first.pow_ - pos->first.pow_
< pos->first.pow_ - left_pos->first.pow_)
pos->second = right_pos->first.id_;
else
pos->second = left_pos->first.id_;
}
cout << pos->first.id_ << " " << pos->second << endl;
}
return 0;
}


6、H06:冷血格斗场

总时间限制: 1000ms 内存限制: 65536kB

描述

为了迎接08年的奥运会,让大家更加了解各种格斗运动,facer新开了一家冷血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。

我们假设格斗的实力可以用一个正整数表示,成为实力值,两人的实力值可以相同。另外,每个人都有一个唯一的id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有多个人的实力值与他差别相同,则他会选择id最小的那个。

不幸的是,Facer一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮facer恢复比赛纪录,按照时间顺序依次输出每场比赛双方的id。

输入

第一行一个数n(0 < n <=100000),表示格斗场新来的会员数(不包括facer)。以后n行每一行两个数,按照入会的时间给出会员的id和实力值。一开始,facer就算是会员,id为1,实力值1000000000。

输出

N行,每行两个数,为每场比赛双方的id,新手的id写在前面。

样例输入

3

2 3

3 1

4 2

样例输出

2 1

3 2

4 2

code for 冷血格斗场

#include <iostream>
#include <map>
using namespace std;
template<class T>
struct Mycmp
{
//定义比较器的规则:按pow值排序,pow相等的id小的排在前面
bool operator()(const T & x, const T & y)
{
if (x.pow_ < y.pow_
|| (x.pow_ - y.pow_ == 0) && (x.id_ < y.id_))
return true;
return false;
}

};
class  CMember
{
public:
int id_;
int pow_;
CMember(int i, int p) :id_(i), pow_(p) { ; }
};

int main()
{
//根据题目说明和比较器的比较规则,没有相等的两个元素,可以用map
map<CMember, int, Mycmp<CMember> > mmp;
map<CMember, int, Mycmp<CMember> >::iterator pos;
map<CMember, int, Mycmp<CMember> >::iterator aim;
map<CMember, int, Mycmp<CMember> >::iterator left_pos;
map<CMember, int, Mycmp<CMember> >::iterator right_pos;
mmp.insert(make_pair(CMember(1, 1000000000), -1));
int t;
int x, y;
cin >> t;
while (t--)
{
cin >> x >> y;
mmp.insert(make_pair(CMember(x, y), -1));
pos = mmp.find(CMember(x, y));
aim = left_pos = right_pos = pos;
//这里不需要考虑右边有pow值相等的元素,即使相等,aim也是id最小的那一个
if (pos == mmp.begin())
{
pos->second = (++aim)->first.id_;
}
//元素被插入到了容器的最后一个位置,可以确定的是目标id在pos的左边
else if (pos == --mmp.end())
{
--aim;
//这里需要向前比较相等的pow,直到得到id最小的那一个
//存储pos左边第一个元素的pow
int p = aim->first.pow_;
while (aim != mmp.begin() && aim->first.pow_ == p)
--aim;
//一直到begin这个位置之前pow都相等
if (aim == mmp.begin())
{
if (aim->first.pow_ == p)
pos->second = aim->first.id_;
else
pos->second = (++aim)->first.id_;
}
//还没有到begin就得到了不等的pow,但aim的pow已经不等了
else
pos->second = (++aim)->first.id_;
}
//得到的pos既不在mmp的第一个,也不是mmp的最后一个
else
{
--left_pos; ++right_pos;
if (right_pos->first.pow_ - pos->first.pow_
< pos->first.pow_ - left_pos->first.pow_)
pos->second = right_pos->first.id_;
//左边的差值比右边的小,或者左边的差值与右边的差值相等
//需要找到与left的pow相等的id最小的那个元素
//左右两个值得差值相等,记着右边的id,并且同时向左寻找pow与left相等的最小的那个id
else
{
int aim_id;
//aim一定在left的左边,向左寻找pow相等的id最小的那个
aim = left_pos;
int p = aim->first.pow_;
while (aim != mmp.begin() && aim->first.pow_ == p)
--aim;
if (aim == mmp.begin())
{
if (aim->first.pow_ == p)
aim_id = aim->first.id_;
else
aim_id = (++aim)->first.id_;
}
else
aim_id = (++aim)->first.id_;
//这里的if else 是为了处理当左右两边差值相等的时候,最小的id可能在pos的右侧
if (right_pos->first.pow_ - pos->first.pow_
> pos->first.pow_ - left_pos->first.pow_)
pos->second = aim_id;
else if (right_pos->first.pow_ - pos->first.pow_
== pos->first.pow_ - left_pos->first.pow_)
{
if (aim_id > right_pos->first.id_)
aim_id = right_pos->first.id_;
pos->second = aim_id;
}
}
}
cout << pos->first.id_ << " " << pos->second << endl;
}
}


7、H07:priority queue练习题

总时间限制: 2500ms 内存限制: 131072kB

描述

我们定义一个正整数a比正整数b优先的含义是:

*a的质因数数目(不包括自身)比b的质因数数目多;

*当两者质因数数目相等时,数值较大者优先级高。

现在给定一个容器,初始元素数目为0,之后每次往里面添加10个元素,每次添加之后,要求输出优先级最高与最低的元素,并把该两元素从容器中删除。

输入

第一行: num (添加元素次数,num <= 30)

下面10*num行,每行一个正整数n(n < 10000000).

输出

每次输入10个整数后,输出容器中优先级最高与最低的元素,两者用空格间隔。

样例输入

1

10 7 66 4 5 30 91 100 8 9

样例输出

66 5

code for priority queue

NOTE:用的方法笨成狗,不得不说。时间的效率就本题来说还说得过去,如果不是非要用priority queue的话还有更合适的解法,比如绕过priority queue,用数组排序,输出首尾等

Memory used:12552kB,内存差点就爆了,有点悬

Time used:494ms

#include <iostream>
#include <algorithm>
#include <cstring>
#include <list>
#include <queue>
using namespace std;
int pri[670000];//pri里面的都是质数
bool Select[10000005];
int SIZE = 0;
//经过计算,在10000000的范围之内有664579个质数
//通过筛选法获得素数数组
void Get_pri()
{
int k = 0;
memset(Select, true, sizeof(Select));
for (int i = 2; i < 10000000; ++i)
{
if (Select[i])
{
pri[k++] = i;
for (int j = 2 * i; j < 10000000; j += i)
Select[j] = false;
}
}
SIZE = k;
}

template<class T>
struct Mycmp
{
bool operator()(const T & x, const T & y)
{
if(x.size_ < y.size_
|| (x.size_ == y.size_) && x.nval < y.nval)
return true;
return false;
}
};

class CNumber
{
public:
int size_;
int nval;
CNumber(int n) :nval(n),size_(0)
{
for (int i = 0; pri[i] < nval; ++i)
if ((nval % pri[i]) == 0)
++size_;
}
friend ostream & operator<<(ostream & os, const CNumber & rhs)
{
os << rhs.nval;
return os;
}
};
int main()
{
Get_pri();
int t, k = 0;
cin >> t;
priority_queue<CNumber, vector<CNumber>, Mycmp<CNumber> > pqu[2];
while (t--)
{
for (int i = 1; i <= 10; ++i)
{
int num;
cin >> num;
pqu[k].push(CNumber(num));
}
cout << pqu[k].top() << " ";
pqu[k].pop();
// 用两个同类型的priority_queue的必要性在于:对于priority_queue而言,top最大,其他的次序随机
// 需要将priority_queue中的element处理到只剩下一个才是优先级最小的
// 在此过程中中间的元素可以用stack也可以用另一个同类型的priority_queue来保存
// 显然用stack存储之后还得再压回原priority_queue
// 用另一个priority_queue对象即可新的priority_queue对象继续操作,节省时间,效率更高
while (pqu[k].size() > 1)
{
pqu[1 - k].push(pqu[k].top());
pqu[k].pop();
}
cout << pqu[k].top() << endl;
pqu[k].pop();
k = 1 - k;
}
return 0;
}


8、H08:编程填空:数据库内的学生信息

总时间限制: 3000ms 内存限制: 20480kB

描述

程序填空,使得下面的程序,先输出

(Tom,80),(Tom,70),(Jone,90),(Jack,70),(Alice,100),

(Tom,78),(Tom,78),(Jone,90),(Jack,70),(Alice,100),

(70,Jack),(70,Tom),(80,Tom),(90,Jone),(100,Alice),

(70,Error),(70,Error),(80,Tom),(90,Jone),(100,Alice),

`******

然后,再根据输入数据按要求产生输出数据

#include <iostream>
#include <string>
#include <map>
#include <iterator>
#include <algorithm>
using namespace std;
// 在此处补充你的代码
// 自定义比较器,默认的比较器设定为Mycmp,降序
template<class T>
struct Mycmp
{
bool operator()(const T &x, const T &y){    return x > y;   }
};
template<class Key,class Value,class Pred = Mycmp<Key> >
class MyMultimap
{
public:
typedef multimap<Key, Value, Pred > mymmp;
// 根据提示,typedef iterator需要typename一起使用
typedef typename multimap<Key, Value, Pred >::iterator iterator;
mymmp mmp;
iterator insert(const pair<Key, Value> & p)
{
return mmp.insert(p);
}
iterator find(const Key & key)
{
return mmp.find(key);
}
void Set(const Key & key, const Value & val)
{
pair<iterator, iterator> p = mmp.equal_range(key);
while (p.first != p.second)
{
(p.first)->second = val;
++(p.first);
}
}
iterator begin() { return mmp.begin(); }
iterator end() { return mmp.end(); }
void clear() { mmp.clear(); }
};
template<class Key, class Value>
// mmp中的每一项都是pair类型,所以参数是const pair<Key, Value> & p
ostream & operator << (ostream & os, const pair<Key, Value> & p)
{
os << "(" << p.first << "," << p.second << ")";
return os;
}
// 在此结束补充的代码
struct Student
{
string name;
int score;
};
template <class T>
void Print(T first,T last) {
for(;first!= last; ++ first)
cout << * first << ",";
cout << endl;
}
int main()
{

Student s[] = { {"Tom",80},{"Jack",70},
{"Jone",90},{"Tom",70},{"Alice",100} };

MyMultimap<string,int> mp;
for(int i = 0; i<5; ++ i)
mp.insert(make_pair(s[i].name,s[i].score));
Print(mp.begin(),mp.end()); //按姓名从大到小输出

mp.Set("Tom",78); //把所有名为"Tom"的学生的成绩都设置为78
Print(mp.begin(),mp.end());

MyMultimap<int,string,less<int> > mp2;
for(int i = 0; i<5; ++ i)
mp2.insert(make_pair(s[i].score,s[i].name));

Print(mp2.begin(),mp2.end()); //按成绩从小到大输出
mp2.Set(70,"Error");          //把所有成绩为70的学生,名字都改为"Error"
Print(mp2.begin(),mp2.end());
cout << "******" << endl;

mp.clear();

string name;
string cmd;
int score;
while(cin >> cmd ) {
if( cmd == "A") {
cin >> name >> score;
if(mp.find(name) != mp.end() ) {
cout << "erroe" << endl;
}
mp.insert(make_pair(name,score));
}
else if(cmd == "Q") {
cin >> name;
MyMultimap<string,int>::iterator p = mp.find(name);
if( p!= mp.end()) {
cout << p->second << endl;
}
else {
cout << "Not Found" << endl;
}
}
}
return 0;
}


输入

输入数据的每一行,格式为以下之一:

A name score

Q name score

name是个不带个空格的字符串,长度小于 20

score是个整数,能用int表示

A name score 表示往数据库中新增一个姓名为name的学生,其分数为score。开始时数据库中一个学生也没有。

Q name 表示在数据库中查询姓名为name的学生的分数

数据保证学生不重名。

输入数据少于200,000行。

输出

对于每个查询,输出学生的分数。如果查不到,则输出 “Not Found”

样例输入

A Tom1 30

A Tom2 40

Q Tom3

A Tom4 89

Q Tom1

Q Tom2

样例输出

(Tom,80),(Tom,70),(Jone,90),(Jack,70),(Alice,100),
(Tom,78),(Tom,78),(Jone,90),(Jack,70),(Alice,100),
(70,Jack),(70,Tom),(80,Tom),(90,Jone),(100,Alice),
(70,Error),(70,Error),(80,Tom),(90,Jone),(100,Alice),
******
Not Found
30
40


提示

1) 编写模板的时候,连续的两个 “>”最好要用空格分开,以免被编译器看作是 ">>"运算符。
VS可能无此问题,但是Dev C++和服务器上的编译环境会有这个问题。
比如 vector<vector<int>> 有可能出错,要改成 vector<vector<int> >

2) 在模板中写迭代器时,最好在前面加上 typename关键字,否则可能会编译错。
VS可能无此问题,但是Dev C++和服务器上的编译环境会有这个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐