SCUT_ACM_PLACTICE #1 STL竞赛入门

——记录一下集训队寒假作业的完成情况以及不足之处

- (一)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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值