——记录一下集训队寒假作业的完成情况以及不足之处
- (一)STL竞赛入门
https://vjudge.net/contest/145672#overview
- A - 487-3279
- 字母对应着数字,把输入的字符串处理一下成数字号码,然后用map储存该号码出现次数,然后把出现超过一下的输出就行。
1.map.find()如果没有找到映射关系的话会返回map.end().
2.map<\string,int>::iterator it,(*it).first得到的是key,(*it).second得到value.
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<list>
#include<queue>
using namespace std;
map<string, int> ma;
int lib[129];
string standard(string a){
string b = "00000000";
int j = 0;
int len = a.length();
for (int i = 0; i < len; i++){
if (a[i] >= '0'&&a[i] <= '9'){ b[j++] = a[i]; }
else if (a[i] >= 'A'&&a[i] <= 'Z'){ b[j++] = lib[a[i]] + '0'; }
if (j == 3){ b[j++] = '-'; }
}
return b;
}
int size;
string str;
int main(){
lib['A'] = lib['B'] = lib['C'] = 2;
lib['D'] = lib['E'] = lib['F'] = 3;
lib['G'] = lib['H'] = lib['I'] = 4;
lib['J'] = lib['K'] = lib['L'] = 5;
lib['M'] = lib['N'] = lib['O'] = 6;
lib['P'] = lib['R'] = lib['S'] = 7;
lib['T'] = lib['U'] = lib['V'] = 8;
lib['W'] = lib['X'] = lib['Y'] = 9;
int n;
cin >> n;
while (n--){
cin >> str;
string a = standard(str);
if (ma.find(a) == ma.end()){
ma[a] = 1;
}
else{
ma[a]++;
}
}
bool aaaa = false;
for (map<string,int>::iterator it = ma.begin(); it != ma.end(); it++){
if (ma[(*it).first]>1){
aaaa = true;
cout << (*it).first << " " << ma[(*it).first] << endl;
}
}
if (aaaa == false){ cout << "No duplicates." << endl; }
return 0;
}
-B - Anagram
要求输出全排列,不过大小规定是:’A’<’a’<’B’<’b’<…<’Z’<’z’,所以默认的next_permutation是不对的,一开始不知道next_permutation可以有第三个参数写cmp,以为只要一开始排序是按要求排好了,结果WA了好多次。
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
using namespace std;
string a;
bool cmp(char a, char b){
if (a >= 97 && b >= 97){ return a < b; }
if (a >= 97){ return (a - 32) < b; }
if (b >= 97){ return (((b - 32)>a) || ((b - 32) == a)); }
return a < b;
}
int main(){
int t;
cin >> t;
while (t--){
cin >> a;
sort(a.begin(), a.end(), cmp);
do{
cout << a << endl;
} while (next_permutation(a.begin(), a.end(), cmp));
}
return 0;
}
C - Double Queue
就是一个优先级队列,有时候要求你把优先级最高的值输出并且pop掉,有时候要求输出优先级最低的并且pop掉。我用的map,map内置的红黑树自动默认按key排序。(用cin,cout超时了)(直接用优先级队列应该也可以做吧,只是当时还不会优先级队列)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<stdio.h>
#include<map>
using namespace std;
map<int, int> Map;
int main(){
int n;
int b, c;
int len = 0;
while (~scanf("%d", &n)){
if (n == 0){ return 0; }
if (n == 3){
if (Map.empty()){ printf("0\n"); continue; }
printf("%d\n", ((*Map.begin()).second));
Map.erase(Map.begin());
}
else if (n == 2){
if (Map.empty()){ printf("0\n"); continue; }
printf("%d\n", ((*--Map.end()).second));
Map.erase(--Map.end());
}
else if (n == 1){
scanf("%d%d", &b, &c);
Map[c] = b;
}
}
return 0;
}
- D - ACboy needs your help again!
一开始给你要求是FIFO还是FILO,然后一序列的in out操作,正确输出并pop掉就行了。(直接用了stl的栈和队列了,自己构造效率肯定更高)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<list>
#include <queue>
#include<vector>
#include<set>
#include<stdio.h>
#include<map>
#include<stack>
#include<queue>
using namespace std;
stack<int> a;
queue<int> b;
int n;
string str;
int main(){
int t;
cin >> t;
int num;
while (t--){
cin >> n;
cin >> str;
if (str == "FIFO"){
while (n--){
cin >> str;
if (str == "IN"){
cin >> num;
b.push(num);
}
else if (str == "OUT"){
if (b.empty()){ cout << "None" << endl; continue; }
printf("%d\n", b.front());
b.pop();
}
}
while (!b.empty()){ b.pop(); }
}
else if (str == "FILO"){
while (n--){
cin >> str;
if (str == "IN"){
cin >> num;
a.push(num);
}
else if (str == "OUT"){
if (a.empty()){ cout << "None" << endl; continue; }
printf("%d\n", a.top());
a.pop();
}
}
while (!a.empty()){ a.pop(); }
}
}
return 0;
}
- E - List of Conquests
输入n行字符串,每行开头是一个国家名,后面是一个女性的名字(有空格),要求输出每一个国家有几个女性。(其实一开始没读懂题目,英文略渣)每一个循环cin读入国家名,后面的字符直接用getchar()读入直到换行符进入下一次循环。
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<stdio.h>
#include<map>
using namespace std;
map<string, int> m;
int main(){
int n;
string str;
cin >> n;
while (n--){
cin >> str;
while (getchar() != '\n'){}
if (m.find(str) == m.end()){ m[str] = 1; }
else{ m[str]++; }
}
for (map<string, int>::iterator it = m.begin(); it != m.end(); it++){
cout << (*it).first << " " << ((*it).second) << endl;
}
return 0;
}
- F - Misha and Changing Handles
用户名更改问题,可能会改很多次,最后结果输出所有人的最初用户名和最终用户名。(用了两个map来保存映射关系,a是最初名字映射到最新名字,b是更改后的名字映射会最初的原名,每次更换用户名的原名如果可以在b映射中找到的话,说明是已经改名过的用户了)(输出用户数量时如果用的a.size()的话就会在某个test中出错,难道是空map输出的不对?后面改用一个变量来计数就对了)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<stdio.h>
#include<map>
using namespace std;
map<string, string> a;
map<string, string> b;
int main(){
int n;
string p, q;
cin >> n;
int ans = 0;
while (n--){
cin >> p >> q;
if (b.find(p) == b.end()){ a[p] = q; b[q] = p; ans++; }
else {
a[b[p]] = q;
b[q] = b[p];
}
}
cout << ans << endl;
for (map<string, string>::iterator it = a.begin(); it != a.end(); it++){
cout << (*it).first << " " << (*it).second << endl;
}
return 0;
}
- G - Ignatius and the Princess II
要求某个数列的某个全排列
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
int a[10005];
int main(){
int n, m;
while (~scanf("%d%d",&n,&m)){
for (int i = 0; i < n; i++){
a[i] = i + 1;
}
while (--m){
next_permutation(a, a + n);
}
for (int i = 0; i < n; i++){
printf("%d", a[i]);
if (i < n - 1){ printf(" "); }
}
printf("\n");
}
return 0;
}
- H - Bombing
一开始给出建筑物的坐标,然后用炸弹炸,每次要嘛炸一行,要嘛炸一列,每次炸要求输出炸毁的建筑数量(炸过的就不算了),才发现原来map的映射可以映射到set里面去,每个建筑都要往x映射和y映射里加入,炸行就把那行的size输出,然后对应的横坐标的x映射里的y删掉。set可以直接按值erase很方便,这题得用multiset(好像是一个坐标点能存在多个建筑吧)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<set>
#include<stdio.h>
#include<map>
using namespace std;
#define M multiset<int>
map<int, multiset<int> >x;
map<int, multiset<int> >y;
int n, m;
int px, py;
int main(){
while (~scanf("%d%d", &n, &m)){
if (n == 0 && m == 0){ return 0; }
x.clear(), y.clear();
for (int i = 0; i < n; i++){
scanf("%d%d", &px, &py);
x[px].insert(py);
y[py].insert(px);
}
for (int i = 0; i < m; i++){
scanf("%d%d", &px, &py);
if (px == 0){
printf("%d\n", x[py].size());
for (M::iterator it = x[py].begin(); it != x[py].end(); it++){
y[*it].erase(py);
}
x[py].clear();
}
if (px == 1){
printf("%d\n", y[py].size());
for (M::iterator it = y[py].begin(); it != y[py].end(); it++){
x[*it].erase(py);
}
y[py].clear();
}
}
printf("\n");
}
return 0;
}
- I - Throw nails
看了别人的题解才会做的,对数据范围还是不够敏感,给出每个选手的第一秒速度fi和后面的速度si,每秒把跑在最前面的砸死,要求输出扔石子的顺序,由于si的范围时0-100,所以只需要100个优先队列(按fi从大到下排序),每次计算所有队列top的那个选手的位置(因为他们si相同,肯定是fi大的那个跑得快),最前面那个被扔石子。
——这里学会自定义优先队列的排序方式了,虽然还不太熟悉。
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<stdio.h>
using namespace std;
struct player{
int n;
int v;
bool operator < (const player& b)const{
return v<b.v || (v == b.v&&n>b.n);
}
};
priority_queue<player> s[101];
int main(){
int t, a, b;
int maxp = 0, maxs = 0, maxy = 0;
cin >> t;
for (int i = 1; i <= t; i++){
int n;
scanf("%d", &n);
for (int j = 1; j <= n; j++){
scanf("%d%d", &a, &b);
s[b].push({ j, a });
}
printf("Case #%d:\n", i);
for (int i = 0; i < n; i++){
maxp = 0, maxs = 0, maxy = 0;
for (int j = 0; j <= 100; j++){
if (!s[j].empty()){
player cnt = s[j].top();
if (cnt.v + j*i>maxs || ((cnt.v + j*i) == maxs&&cnt.n < maxp)){
maxp = s[j].top().n, maxs = (cnt.v + j*i), maxy = j;
}
}
}
printf("%d", maxp);
s[maxy].pop();
if (i < n - 1){ printf(" "); }
}
printf("\n");
}
return 0;
}
- J - What Are You Talking About
map映射题,给你单词映射方式,然后给你一句话让你翻译,不在单词映射关系的就不用翻译了。(空格,标点符号那些的都直接输出不用考虑翻译)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<stdio.h>
#include<map>
using namespace std;
map<string, string> dic;
int main(){
string a, b, str;
cin >> str;
while (cin >> a){
if (a == "END"){ break; }
cin >> b;
dic[b] = a;
}
cin >> str;
getchar();
while (getline(cin, str)){
if (str == "END"){ break; }
int len = str.length();
for (int i = 0, j = 0; j < len; j++){
if (str[j] >= 'a'&&str[j] <= 'z'){
if (j == len - 1){
string cnt = str.substr(i, j - i + 1);
if (dic.find(cnt) != dic.end())
cout << dic[cnt];
else
cout << cnt;
break;
}
continue;
}
else{
if (i == j){ cout << str[i]; i++; continue; }
else{
string cnt = str.substr(i, j - i);
if (dic.find(cnt) != dic.end())
cout << dic[cnt];
else
cout << cnt;
i = j;
j--;
continue;
}
}
}
cout << endl;
}
return 0;
}
====这些题目对于熟悉stl的人来说很好做,不过其实不用stl的话也都能做,而且效率更高,也不受约束,所以不能太依赖stl。