STL做题(暂时有些东西还不大理解,以后还会回来补注解)

1806:词典

题目
描述
你旅游到了一个国外的城市。那里的人们说的外国语言你不能理解。不过幸运的是,你有一本词典可以帮助你。

输入
首先输入一个词典,词典中包含不超过100000个词条,每个词条占据一行。每一个词条包括一个英文单词和一个外语单词,两个单词之间用一个空格隔开。而且在词典中不会有某个外语单词出现超过两次。词典之后是一个空行,然后给出一个由外语单词组成的文档,文档不超过100000行,而且每行只包括一个外语单词。输入中出现单词只包括小写字母,而且长度不会超过10。
输出
在输出中,你需要把输入文档翻译成英文,每行输出一个英文单词。如果某个外语单词不在词典中,就把这个单词翻译成“eh”。
样例输入
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay

atcay
ittenkay
oopslay
样例输出
cat
eh
loops
注意cin.putback(tmp);的妙用:将tmp里存放的内容返回输入流中

#include <bits/stdc++.h>
#include<string>
using namespace std;
map<string,string>m;
map<string,string>::iterator it;//迭代器 作用:相当于数组里的下标
string a,b,c;
char tmp;
int main(){
	while((tmp=cin.get())!='\n'){//判断是否结束输入
		cin.putback(tmp);//返回输入流
		cin>>a>>b;//键盘输入的两个字符串存放在a b中
		m[b]=a;//放入命名为m的map中
		getchar();//收回车
	}
	while(cin>>c){
		it=m.find(c);//在名字为m的map中寻找有无c的存在,如果it==m.end()说明未找到
		if(it!=m.end()) cout<<it->second<<endl;
		else cout<<"eh"<<endl;
	}
    return 0;
}

3339:List

描述
写一个程序完成以下命令:
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

#include <bits/stdc++.h>
#include<string>
using namespace std;
list<int>m[10010];
list<int>::iterator it;//迭代器 作用:相当于数组里的下标 
string a;
int n,id,id1,id2,num;
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a;
		if(a=="new") cin>>id;
		if(a=="add"){
			cin>>id>>num;
			m[id].insert(m[id].end(),num);
		}
		if(a=="merge"){
			cin>>id1>>id2;
			m[id1].merge(m[id2]);
		}
		if(a=="unique"){
			cin>>id;
			m[id].sort();
			m[id].unique();
		}
		if(a=="out"){
			cin>>id;
			m[id].sort();
			for(it=m[id].begin();it!=m[id].end();it++)
				cout<<*it<<' ';
			cout<<endl;
		}
	}
    return 0;
}

3341:Set

题目
描述
现有一整数集(允许有重复元素),初始为空。我们定义如下操作:
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

#include <bits/stdc++.h>
#include<string>
using namespace std;
multiset<int>a;
map<int,bool>b;
//list<int>::iterator it;//迭代器 作用:相当于数组里的下标 
string m;
int n,x;
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>m>>x;
		if(m=="add"){
			a.insert(x);
			b[x]=1;
			cout<<a.count(x)<<endl;
		}
		if(m=="del"){
			cout<<a.count(x)<<endl;
			a.erase(x);
		}
		if(m=="ask"){
			cout<<b[x]<<' '<<a.count(x)<<endl;
		}
	}
    return 0;
}

3342:字符串操作

题目
描述
给定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
不会。。。。。

3343:热血格斗场

题目
描述
为了迎接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
注意:1.map会自动将实力值按从小到大的顺序排列
2.mp.end()这个位置上是没有值的相当于一个尾指针,指向NULL的感觉

#include <bits/stdc++.h>
#include<string>
using namespace std; 
map<int,int>mp;
map<int,int>::iterator it; 
int m,n;
int main(){
	mp[1000000000]=1;//facer
	cin>>n;
	while(n--){
		int id,zhi;
		cin>>id>>zhi;
		it=mp.upper_bound(zhi);//找到第一个>zhi的地址 
		if(it==mp.end())//已经找完了,找不到比新人更强的人了 
			it--;//到老会员中实力值最强的
		int a=abs(it->first-zhi);//实力差
		int oldid=it->second;
//		如果 it==mp.begin();说明新人比最弱的老会员还菜那就只能和最弱的老会员pk了 
		if(it!=mp.begin()&&it!=mp.end()){// 说明新人要和中间某一个老会员 pk需要比较前后老会员差值去最优 
			it--;//实力值比前一个老会员弱的老会员
			int b=abs(zhi-it->first);
			if(b<=a) 
				oldid=it->second;
		} 
		cout<<id<<' '<<oldid<<endl;
		mp[zhi]=id;//将这个新人放进map里 
	}
    return 0;
}

3344:冷血格斗场

题目
描述
为了迎接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
思路:这题主要是存数据进map的时候需要判断之前有无实力值相同的存在,如果有只存id最小的进去,这样就不用在遇到相同实力差的时候还要去一个个找谁的id最小了

#include <bits/stdc++.h>
#include<string>
using namespace std; 
map<int,int>mp;
map<int,int>::iterator it; 
int m,n;
int main(){
	mp[1000000000]=1;//facer
	cin>>n;
	while(n--){
		int id,zhi;
		cin>>id>>zhi;
		it=mp.upper_bound(zhi);//找到第一个>zhi的地址 
		if(it==mp.end())//已经找完了,找不到比新人更强的人了 
			it--;
		int a=abs(it->first-zhi);//实力差
		int oldid=it->second;
//		如果 it==mp.begin();说明新人比最弱的老会员还菜那就只能和最弱的老会员pk了 
		if(it!=mp.begin()&&it!=mp.end()){// 说明新人要和中间某一个老会员 pk需要比较前后老会员差值去最优 
			it--;
			int b=abs(zhi-it->first); 
			if(b<a||b==a&&it->second<oldid){
//当b<a时或者b==a且it指向的这个老会员的id比前一个id也就是oldid小
				oldid=it->second;
		} 
		cout<<id<<' '<<oldid<<endl;
		if(mp[zhi]==0||mp[zhi]>id)//比较巧用未赋值的位置值为0 
			mp[zhi]=id;//由于题目说实力差相同取id最小,所以存的时候相同实力值只存id最小的那个 
//		if(mp.find(zhi)!=mp.end()){//此方法会超时 
//			mp[zhi]=min(mp[zhi],id);
//		}
//		else mp[zhi]=id;
	}
    return 0;
} 

注意:if(b<a||b==a&&it->second<oldid)这步实际上也可以写成if(b<a||(b==a&&it->second<oldid)),而不要把它误认为if((b<=a)&&it->second<oldid),注意&&的优先级高于||,对它的理解请参考上述代码注释

3345:priority queue练习题

题目
描述
我们定义一个正整数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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值