STL(所见过的技巧和用法总结)

STL(Standard Template Library)

在程序设计竞赛中,偶尔会碰到一些需要用特殊结构来解决的问题,这时,灵活运用STL库中的一些数据结构会加速问题的解决,这里,我写了一些我碰到过的应用案例,帮助理解STL的强大。

虽然这些特殊的结构可以解决很多问题,但是性能较差,对于一些时间、空间性能要求比较高的题目并不适用。


目录

STL(Standard Template Library)

set

单词数 HDOJ - 2072

map

Shopping HDOJ - 2648

Intelligent IME HDOJ - 4287

水果 HDOJ - 1263

优先队列  priority_queue

Windows Message Queue HDOJ - 1509

The kth great number HDOJ - 4006


set

简单介绍:说白了就是一个元素不会重复的容器,比如你往容器里放一个集合{1,1,2},容器里就只会有{1,2},也就是这里面的每个元素值都是唯一的,而且系统会根据元素的值对元素进行排序,但是容器里的元素值不能直接被改变。

具体怎么使用:相关的函数及其使用细节请自行搜索~这些就不在这里赘述了,这里就只放一些题目和解决方法。

 

单词数 HDOJ - 2072

题目链接

题意:输入一篇文章,文章内的单词间用空格隔开,文章以符号“#”结束,计算文章内不重复的单词数并输出结果。

分析:利用set容器的特点,将文章的所有单词都存到set容器里,在遇到结束符号的时候输出max_size。

AC代码:

//HDOJ - 2072
#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
#include<sstream>
using namespace std;
char s[1000000];
int main()
{
    while(gets(s))
    {
        set<string>p;//set是关联容器,里面的元素不会重复
        if(!strcmp(s,"#"))
            break;
        stringstream ss(s);
        string di;//
        while(ss>>di)//遇到空格截断,把ss里的内容复制到di里
            p.insert(di);//元素插入
        cout<<p.size()<<endl;//容器里的元素个数
    }
    return 0;
}//MIC_H

map

简单介绍:一个映射容器,以键值对(key-value)为单位存储元素,key值必须唯一,value值可以重复,且容器有自动排序的特点。
用数组来帮助理解,数组可以用a[0]来获取数组里位置0的元素,此时0就是key,a[0]就是value,数组和map不同的是,map里面的key可以用其他数据类型来定义,如string等,例如可以用map来存储一群人的名字和对应的年龄,通过他们的名字可以获得他们的年龄值。

具体怎么使用:相关的函数及其使用细节请自行搜索~这些就不在这里赘述了,这里就只放一些题目和解决方法。

 

Shopping HDOJ - 2648

题目链接

题意:一开始输入n个店的店名,然后输入天数,要求输出每一天memory的排名(从大到小)。

分析:每一天都遍历集合里的元素(),memory的初始rank为1,当遇到比memory的价格大的店时,rank+1,遍历完所有的店之后,此时的rank就是这一天memory的排名。

AC代码:

//HDOJ - 2648
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <functional>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <climits>
#include <string>
using namespace std;

map<string,int>mp;///商店名字为key,每天更新商店的价格
string name[10009];
int main()
{
    int n,m,num;
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>name[i];
            mp[name[i]]=0;
            if(name[i]=="memory")
                num=i;///方便写代码,也可以不这样写
        }
        cin>>m;
        while(m--)
        {
            string ss;
            int rank=1;
            int rise;
            for(int i=0;i<n;i++)
            {
                cin>>rise>>ss;
                mp[ss]+=rise;
            }
            for(int i=0;i<n;i++)///遍历,找多少家商店的价格比memory的高
                 if(mp[name[i]]>mp[name[num]]) ///比memory的高,memory的排名就+1
                   rank++;
            cout<<rank<<endl;
        }
    }
    return 0;
}//MIC_H

Intelligent IME HDOJ - 4287

题目链接

题意:给出输入顺序和字典,要求输出在字典里找到的匹配单词的个数。

分析:用数组ch记录各个字母的键盘位置,然后每输入一个单词就对相应的字符串映射的值++,最终各个输出。

AC代码:

//HDOJ - 4287
#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#define mod 10007
using namespace std;

char ch[30]={'2','2','2','3','3','3','4','4','4','5','5','5'
,'6','6','6','7','7','7','7','8','8','8','9','9','9','9'};
map<string,int> ma;
string a[5050];

int main()
{
    int t,n,m;
    string s1,s2;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            cin>>s1;
            a[i]=s1;
            ma[s1]=0;
        }
        for(int i=0;i<m;i++)
        {
            cin>>s1;
            s2="";
            for(unsigned j=0;j<s1.size();j++)//将单词转换成输入顺序
                s2+=ch[s1[j]-'a'];
            ma[s2]++;
        }
        for(int i=0;i<n;i++)
            cout<<ma[a[i]]<<endl;
    }
    return 0;
}//MIC_H

水果 HDOJ - 1263

题目链接

题意:给出一组数据,每行数据分别包括水果名称、水果产地、水果销量,要求输出每个产地各种水果的销售量。

分析:映射关系为地名->水果->销售数目,需要用两个map嵌套实现,每输入一行数据,就更新map,具体见代码。

AC代码:

//HDOJ - 1263
#include<iostream>
#include<string>
#include<map>
using namespace std;

struct MyStruct
{
	map <string, int>MyStructma;  //存放水果名以及该种水果的数量
};
int main()
{
	map <string, MyStruct>ma;    //地名
	map <string, MyStruct>::iterator it;
	map <string, int>::iterator MyStructmait;
	string fruit,place;
	int count;
    	int n,t;
	cin>>t;
	while(t--)
	{
		ma.clear();
		cin>>n;
		while(n--)
		{
			cin>>fruit>>place>>count;
			ma[place].MyStructma[fruit] += count;
		}
		for (it = ma.begin(); it != ma.end(); it++)
		{
			cout<<it->first<<endl;
			for (MyStructmait = it->second.MyStructma.begin(); MyStructmait != it->second.MyStructma.end(); MyStructmait++)
			{
				cout<<"   |----"<<MyStructmait->first<<"("<<MyStructmait->second<<")"<<endl;
			}
		}
		if(t != 0)cout<<endl;
	}
	return 0;
}//MIC_H

 


优先队列  priority_queue

简单介绍:特点是队列最大的元素总是在队首(默认情况),每插入一个元素,队列就会进行调整。可以自己设置队列里面的排序规则。

具体怎么使用:相关的函数及其使用细节请自行搜索~这些就不在这里赘述了,这里就只放一些题目和解决方法。

 

Windows Message Queue HDOJ - 1509

题意:输入一系列GET和PUT命令,要求显示输出结果。当命令是PUT时,无输出,当命令是GET时,若此时队列不为空,则获取优先级最高的消息并输出,若队列为空,则显示"EMPTY QUEUE!"。

分析:用优先队列对输入的PUT消息里的内容进行排序,排序根据为优先级和时间顺序,优先级一致时,时间顺序靠前的排名较高。具体见代码。

AC代码:

//HDOJ - 1509
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#define mod 10007
using namespace std;

struct message
{
    string name;
    int val;
    int ran;
    int t;
    friend bool operator < (message m1,message m2)//优先队列里的排序规则
    {
        if(m1.ran!=m2.ran)
            return m1.ran > m2.ran;
        else
            return m1.t>m2.t;
    }
};
int main()
{
    priority_queue<message>m;
    string ope;
    int time=0;
    message mm;
    while(cin>>ope)
    {
        if(ope=="GET")
        {
            if(m.empty())
                printf("EMPTY QUEUE!\n");
            else
            {
                cout<<m.top().name<<' '<<m.top().val<<endl;
                m.pop();
            }
        }
        else
        {
            cin>>mm.name>>mm.val>>mm.ran;
            mm.t=++time;
            m.push(mm);
        }
    }
    return 0;
}//MIC_H

The kth great number HDOJ - 4006

题意:输入n和k,分别代表接下来有n个操作,如果是I操作,就是向队列里插入元素,如果是Q操作,就是输出第k大的元素。

分析:保证队列里最多只有k个元素,个数小于k则插入队列,若队列元素个数已为k,判断此时想要插入的元素是否大于队列中的最小值(队尾元素),如大于则把队尾元素删除,插入此yuan's,这样,队尾就会是第k大的值。

AC代码:

//HDOJ - 4006
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <set>
#include <queue>
#include <sstream>
using namespace std;

int main()
{
    int i,n,wro;
    unsigned k;
    char ope;
    while(cin>>n>>k)
    {
        priority_queue<int,vector<int>,greater<int> >nn;
        for(i=0;i<n;i++)
        {
            cin>>ope;
            if(ope=='I')
            {
                cin>>wro;
                if(nn.size()<k)
                    nn.push(wro);
                else if(nn.top()<wro)
                {
                    nn.pop();
                    nn.push(wro);
                }
            }
            else
                cout<<nn.top()<<endl;
        }
    }
    return 0;
}//MIC_H

=======最后更新时间:2019.07.26=======

=======遇到好的题目会回来继续更新======

===如果各位大牛牪犇路过发现问题欢迎反映  (「・ω・)「嘿===

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值