10道ACM例题让你三天学会STL

  清明节给大一的孩子们讲了点STL的应用,下了些功夫,搬到这里来供大家学习交流。

  1.泛型程序设计简介与迭代器的介绍

  2.常见的STL容器及其例题应用(UVA10474,UVA101,UVA10815,UVA156,UVA540,UVA136

HDU1027,CF501B,HDU1716,HDU4277)

  3.相关练习和思路

1.泛型程序设计简介与迭代器的介绍

1.1 泛型程序设计简介

  泛型程序设计,简单地说就是使用模板的程序设计法。将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法。

  总而言之,不多赘述,有了STL,不必再从头写大多的标准数据结构和算法,并且可获得非常高的性能。

1.2迭代器

  • 可遍历STL容器内全部或部分元素的对象
  • 指出容器中的一个特定位置
  • 所有容器都提供获得迭代器的函数
操作 效果
begin() 返回一个迭代器,指向第一个元素
end() 返回一个迭代器,指向最后一个元素之后

  半开区间[beg, end)的好处:

  1.为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)

  2.不必对空区间采取特殊处理(空区间的begin()就等于end())

2.常见的STL容器及其例题应用

2.1Sort

例题1:UVA 10474 Where is the Marble

题目:题目意思就是给出两个数m和n下面输入m个数,再依次输入n个数,查找n个数在前面的m个数中是第几大

思路很简单,排序加查找(也可以二分优化)。

这里简述sort函数的用法

头文件: <algorithm>

格式:

sort(vect.begin(), vect.end());

sort(vect.begin(), vect.end(), less<int>() );

第三个参数可以自定义,主要用于自定义类型的排序

2.2Vector

2.2.1用法:

vector<类型> 名字;

例如 vector<int> ve; vector<string> ve;

自己定义的结构体什么的也可以往里塞

struct POINT

{

int x, y;

};

vector<POINT> ve;

2.2.2基本操作

ve.push_back(const value_type &val);

作用是在数组后面增加一个元素。括号里填的是ve里装的东西

ve.clear();清空ve里的所有元素。

ve.empty();判断ve是否为空,如果是返回true,否则false

ve.size();返回ve的长度。注意这里返回的类型是unsigned int,如果ve是空的ve.size() - 1就会爆掉。使用的时候一定要小心(做TC的时候被坑了一次)

ve.pop_back() 删除数组里的最后一个元素。

2.2.3例题

例题2:UVA101 The Blocks Problem

题目:给你n个方块,有四种操作:

1.move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面;

2.move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上面;

3.pile a onto b,把b上面的放回原来位置,然后把a和a上面的方块整体放到b上面;

4.pile a over b,把a和a上面的方块整体放到b所在堆的上面。

定义两个基本操作:

1.将a上面的还原init_place(a);

2.将a和上面的(可以没有上面的)放到b上面pile_a_to_b(a,b)。

那么上述的四组操作就变成下面了:

1.move a onto b,init_place(a);init_place(b);pile_a_to_b(a,b);

2.move a over b,init_place(a);pile_a_to_b(a,b);

3.pile a onto b,init_place(b);pile_a_to_b(a,b);

4.pile a over b,pile_a_to_b(a,b)。

我这里用哈希写的,O(N)

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 10474 - Where is the Marble?
   总结:sort使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 10000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
using namespace std;
int arr[MAXN];
int hash[MAXN];
int main()
{
//    freopen("in.txt","r",stdin);
    int n,q,ca=1;
    while(scanf("%d %d",&n,&q)&&(n+q))
    {
        mem(hash,-1);
        bool flag=false;
        printf("CASE# %d:\n",ca++);
        Rep(i,n)
            scanf("%d",&arr[i]);
        sort(arr,arr+n);
        Rep(i,n)
        {
            if(arr[i]!=arr[i-1])//不加的话会wa
                hash[arr[i]]=i+1;
        }
        int ques;
        Rep(i,q)
        {
            flag=false;
            scanf("%d",&ques);
            if(hash[ques]!=-1)
            printf("%d found at %d\n",ques,hash[ques]);
            else
            printf("%d not found\n",ques);
        }
    }
    return 0;
}

2.3 Set

2.3.1用法:

set<类型> 名字;

例如 set<int> se; set<string> se;

自己定义的结构体什么的也可以往里塞

struct POINT

{

int x, y;

};

set<POINT> se;

2.3.2基本操作对集合a中元素的有

插入元素:a.insert(1);

删除元素(如果存在):a.erase(1);

判断元素是否属于集合:if (a.find(1) != a.end()) ...

返回集合元素的个数:a.size()

将集合清为空集:a.clear()

2.3.3例题

例题3:UVA 10815 Andy‘s First Dictionary

题目:给出一串单词,把所有单词改小写去重按字典序输出。

思路:set可以解决去重和排序问题。

set中每个元素最多只出现一次

set中的元素已经从小到大排序好

如何通过迭代器从小到大遍历所有元素

for (set<string>::iterator i = d.begin(); i != d.end(); i++)

cout << *i << endl;

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 10815 - Andy's First Dictionary
   总结:set使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

using namespace std;
set<string>jihe;

int main()
{

//    freopen("in.txt","r",stdin);

    string sen;
    while(getline(cin,sen))
    {
        for(int i=0;i<sen.size();i++)
        {
            if(!isalpha(sen[i])) continue;
            string tmp;
            while(isalpha(sen[i]))
            {
                tmp+=tolower(sen[i]);
                i++;
            }
            jihe.insert(tmp);
        }
    }
    for(set<string>::iterator it=jihe.begin();it!=jihe.end();it++)
    {
        cout<<*it<<endl;
    }
    return 0;
}<strong>
</strong>

2.4 Map

2.4.1用法:

map添加数据;

map<int ,string> maplive;  //第一个是键值,第二个是值

1.maplive.insert(pair<int,string>(102,"aclive"));

2. maplive[112]="April";//map中最简单最常用的插入添加!

map中查找数据:

第一种:用count 函数来判定关键字是否出现,其缺点是无法定位数据出现位置,

由于map 的特性,一对一的映射关系,就决定了count 函数的返回值只有两个,

要么是0,要么是1,出现的情况,当然是返回1 了

第二种:用find 函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map 中没有要查找的数据,它返回的迭代器等于end 函数返回的迭代器

注意:

Map中的元素是自动按key升序排序,所以不能对map用sort函数

但可以用迭代器按序遍历(与set类似)

2.4.2例题

例题4:UVA 156 Ananagrams

题目:把每个单词全部转化成小写字母,对每个单词,看它的字母重排后得到的单词在所有输入的单词中是否出现过,若没有出现,就输出原单词。所有要输出的单词按字典序排列输出。

思路:构造小写化函数,set可以解决去重和排序问题,用map建立string与int的映射

void string stand_words(string s1);

注意要存储原单词!

ps:也可以用multimap建立string与string的多重映射,即原单词与现单词的映射,方便提取原单词操作

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 156 - Ananagrams
   总结:map+set+vector使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
using namespace std;

map<string,int> hash;//标准句子出现次数
string record[MAXN];//所有原来的句子
set<string> ans;//所有答案
void standard(string& s1)
{
    string ans;
    Rep(i,s1.size())
        s1[i]=tolower(s1[i]);
    sort(s1.begin(),s1.end());
}
int main()
{
//    freopen("in.txt","r",stdin);
    string sen;
    int index=0;
    while(getline(cin,sen))
    {
        if(sen[0]=='#')
            break;
        Rep(i,sen.size())
        {
            string tmp;
            if(!isalpha(sen[i]))continue;
            while(isalpha(sen[i]))
            {
                tmp+=sen[i];
                i++;
            }
            record[index++]=tmp;
            standard(tmp);
            hash[tmp]++;
        }
    }
    Rep(i,index)
    {
        string tmp=record[i];
        standard(tmp);
        if(hash[tmp]==1)
            ans.insert(record[i]);
    }
    for(set<string>::iterator it=ans.begin(); it!=ans.end(); it++)
        cout<<*it<<endl;
    return 0;
}
/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 156 - Ananagrams
   总结:multimap使用练习
   Tricks:string利用构造函数拷贝
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
using namespace std;

multimap<string,string> hash;//从标准到原句子
set<string> ans;//所有标准句子
void standard(string& s1)
{
    string ans;
    Rep(i,s1.size())
    {
        s1[i]=tolower(s1[i]);
    }
    sort(s1.begin(),s1.end());
}
int main()
{
    freopen("in.txt","r",stdin);
    string sen;
    while(getline(cin,sen))
    {
        if(sen[0]=='#')
            break;
        Rep(i,sen.size())
        {
            string tmp;
            if(!isalpha(sen[i]))continue;
            while(isalpha(sen[i]))
            {
                tmp+=sen[i];
                i++;
            }
            string ttmp=tmp;
            standard(tmp);
            hash.insert(MP(tmp,ttmp));
        }
    }
    for(map<string,string>::iterator it=hash.begin();it!=hash.end(); it++)
    {
//        cout<<it->second<<" "<<hash.count(it->second)<<endl;
        if(hash.count(it->first)==1)
            ans.insert(it->second);
    }
    for(set<string>::iterator it=ans.begin(); it!=ans.end(); it++)
    {
        cout<<*it<<endl;
    }
    return 0;
}

2.5 Queue

2.5.1用法

和vector一样。

queue<int> qu;

queue<POINT> qu;

我一般都用它在BFS的时候存点。

2.5.2 常用操作

qu.push(const value_type &val); 元素入队

qu.pop()元素出队

qu.front() 获得队首元素

qu.empty() 判断qu是否为空,是的话返回true

qu.size() 获得qu的大小。

2.5.3例题

例题5:UVA 540 Ananagrams

题目:题意:有t个团队的人在排队。每次来了一个新人之后,如果他有队友在排队,那么这个新人会插队到队友的身后。要求支持三种指令:ENQUEUE x; DEQUEUE(队首出队); STOP。模拟这个过程,输出出队顺序

思路:模拟题。每个队列在一个大队列排队

queue<int> q,  q2[maxt];

q为总的团队队列,q2为每个团队的队列

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 540 - Team Queue
   总结:queue使用练习
   Tricks:可能重复入队出队
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

using namespace std;

int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    int ca=1;
    while(scanf("%d",&T)&&T)
    {
        printf("Scenario #%d\n",ca++);
        queue<int>zhudui;
        queue<int>meige[MAXN];
        vector<int>record[MAXN];
        bool zhuvis[MAXN];
        mem(zhuvis,0);
        Rep(j,T)
        {
            int n;
            scanf("%d",&n);
            Rep(i,n)
            {
                int tmp;
                scanf("%d",&tmp);
                record[j].PB(tmp);
            }
        }
        string s1;
        int num;
        while(cin>>s1)
        {
            if(s1=="STOP")
                break;
            if(s1=="ENQUEUE")
            {
                cin>>num;
                int index=-1;
                Rep(i,T)
                {
                    vector<int>::iterator result=find(record[i].begin(),record[i].end(),num);
                    if(result==record[i].end()) //没找到
                        continue;
                    else
                    {
                        index=i;
                        break;
                    }
                }
                if(index!=-1)
                {
                    meige[index].push(num);//某人入某队
                    if(!zhuvis[index])
                    {
                        zhuvis[index]=true;
                        zhudui.push(index);//该队入主队
                    }
                }
            }
            else if(s1=="DEQUEUE")
            {
                int duii=zhudui.front();
                int ansi=meige[duii].front();
                meige[duii].pop();
                if(!meige[duii].size())
                {
                    zhudui.pop();
                    zhuvis[duii]=false;//没有的话会RE
                }
                cout<<ansi<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}

2.6 priority_queue(优先队列):默认从大到小排列。

2.6.1用法

priority_queue<int> pqu;

如果要装结构体的话,要重载结构体的小于号,或者自己写一个cmp函数。

struct cmp

{

operator bool ()(int x, int y)

{

return x > y; // x小的优先级高

}

};

priority_queue<int, vector<int>, cmp>q;//第二个参数为容器类型。第三个参数为比较函数。

priority_queue<vector<int>, less<int>> pq1; // 使用递减less<int>函数对象排序

priority_queue<deque<int>, greater<int>> pq2; // 使用递增greater<int>函数对象排序

常用操作

push(),top(),pop(),empty();

2.6.2 例题

例题6:UVA 136 Ugly Number

题目:把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求出第n个丑数。

思路:利用优先队列

//最后不要挨到一起,默认为位运算

priority_queue<LL,vector<LL>,greater<LL> >pq;

注意用long long!

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 136 - Ugly Numbers
   总结:优先队列使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

int ref[3]={2,3,5};
using namespace std;
int main()
{
//    freopen("in.txt","r",stdin);
    priority_queue<LL,vector<LL> ,greater<LL> >pq;
    set<LL>record;
    pq.push(1);
    record.insert(1);
    int ca=1;
    while(!pq.empty())
    {
        LL tmp=pq.top();
        pq.pop();
        if(ca==1500)
        {
            printf("The 1500'th ugly number is %lld.\n",tmp);
            break;
        }
        Rep(i,3)
        {
            LL ttmp=tmp*ref[i];
            if(!record.count(ttmp))
            {
                record.insert(ttmp);
                pq.push(ttmp);
            }
        }
        ca++;
    }
    return 0;
}

也可以用set直接判重输出,这是我的写法:

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: UVA 136 - Ugly Numbers
   总结:set使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define viti (vector<int>::iterator)
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define MID(a, b) (a + ((b - a) >> 1)) 1
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

using namespace std;

set<LL>Ch;
int ref[3]={2,3,5};
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int ca=1;
    Ch.insert(1);
    set<LL>::iterator it=Ch.begin();
    while(ca<=2000)
    {
        it=Ch.begin();
        for(it;it!=Ch.end()&&ca<=2000;it++)
        {
            Rep(j,3)
            {
                LL tmp=(*it)*ref[j];
                if(Ch.find(tmp)==Ch.end())
                {
                    Ch.insert(tmp);
                    ca++;
                }
            }
        }
    }
    ca=1;
    it=Ch.begin();
    for(it;it!=Ch.end()&&ca++<1500;it++);
    printf("The 1500'th ugly number is %lld.\n",*it);
    return 0;
}

2.7 next_permutation(全排列):要包含头文件<algorithm>

2.7.1用法

与之完全相反的函数还有prev_permutation

a[0]=1;a[1]=2;a[2]=3;

do{cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;}while (next_permutation(a,a+3));

输出:

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

如果改成 while(next_permutation(a,a+2));

则输出:

1 2 3

2 1 3

只对前两个元素进行字典排序

2.7.2 例题

例题7:HDU 1027 Ignatius and the Princess II

题目:求N个数全排列,顺着数第M个

思路:利用next_permutation

while(m--)

{

next_permutation(num,num+n);

}

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: HDU 1027 - Ignatius and the Princess II
   总结:next_permutation使用练习
   Tricks:
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

int arr[MAXN];
using namespace std;
int main()
{
//    freopen("in.txt","r",stdin);
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            arr[i]=i;
        int ca=1;
        do
        {
            if(ca==m)
            {
                int i;
                for(i=1;i<n;i++)
                {
                    cout<<arr[i]<<" ";
                }
                cout<<arr[i]<<endl;
                break;
            }
            ca++;
        }while(next_permutation(arr+1,arr+n+1));
    }
    return 0;
}

例题9:HDU 1716 排列2

思路同理

注意输出格式易PE:每行末尾无0,最后一组数据末尾没有回车!

/*********************************
   日期:2015-04-03
   作者:
   题号: HDU 1716 - 排列2
   总结:next_permutation的使用
   Tricks:0开始的忽略
           重复的不计
           写吐了,while里面乱搞的。。。出题不善,大家跳过这个题吧
**********************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <map>
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define N 10010
using namespace std;
int vis[12];
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int a[6];
    scanf("%d %d %d %d",&a[1],&a[2],&a[3],&a[4]);
    if(!(a[1]+a[2]+a[3]+a[4]))
        return 0;
    do
    {
        bool mark=false;
        mem(vis,0);
        for(int i=1; i<=4; i++)
        {
            vis[a[i]]++;
        }
        sort(a+1,a+5);
        int tmp=a[1];
        int cnt=1;
        do
        {
            if(a[1]==0)
                continue;
            if(a[1]!=tmp)
            {
                mark=false;
                if(tmp!=0)
                    cout<<endl;
                tmp=a[1];
            }
            else if(vis[a[1]]>1)
            {
                    vis[a[1]]--;
                    cnt++;
            }
            if(mark)
            {
                cout<<" ";
            }
            else
                mark=true;
            cout<<a[1]<<a[2]<<a[3]<<a[4];
        }while(next_permutation(a+1,a+5));
        cout<<endl;
        scanf("%d %d %d %d",&a[1],&a[2],&a[3],&a[4]);
        if(a[1]+a[2]+a[3]+a[4])
            cout<<endl;
        else
            break;
    }while(1);
    return 0;
}

3.相关练习和思路

3.1

例题8:Codeforces 501B - Misha and Changing Handles

题目:有一些人改名字,输出每个人的原名和改了之后的名字.

思路:用map记录每个人换过的名字,用set记录是不是一个新的人,如果是的话就放到数组里。

/*********************************
   日期:2015-04-05
   作者:matrix68
   题号: Codefores 501B - Misha and Changing Handles
   总结:map使用练习
   Tricks:建立新名字到旧名字的映射,把所有新名字放在set里排重。
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
const double PI = acos(-0);
const int MAXN = 1000 + 10;
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
using namespace std;

map<string,string>x_j;//新名字到旧名字的映射
set<string>newn;//新名字

int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    string s1,s2;
    while(T--)
    {
        cin>>s1>>s2;
        if(!(newn.find(s1)==newn.end()))//新名字集合里找到s1
        {
            x_j[s2]=x_j[s1];
            x_j[s1]=x_j[s1];
            x_j.erase(s1);
            newn.erase(s1);
            newn.insert(s2);
        }
        else
        {
            newn.insert(s2);
            x_j[s2]=s1;
        }
    }
    cout<<newn.size()<<endl;
    for(set<string>::iterator it=newn.begin();it!=newn.end();it++)
    {
        cout<<x_j[*it]<<" "<<*it<<endl;
    }
    return 0;
}

3.2

例题10:HDU 4277 - USACO ORZ

题目:给定一些一定长度的线段,要求全部利用这些线段能拼成多少种三角形(如果两个三角形至少有一条边长度不等那么二者视为两种)

思路:DFS,对于所有满足情况的三角形加入set中,这样就去重了,最后set的大小就是答案

set里面可以存两种:

自定义struct Past但必须重载<

LL构造每个三角形的唯一值

/*********************************
   日期:2015-04-03
   作者:matrix68
   题号: HDU 4277 - USACO ORZ
   总结:DFS+set
   Tricks:注意用long long
**********************************/
#include <cstdio>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <cmath>
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define PB push_back
#define Lowbit(x) ((x) & (-x))
#define Rep(i,n) for(int i=0;i<n;i++)
#define mem(arr,val) memset((arr),(val),(sizeof (arr)))
#define LL long long
#define N 20
#define M 1000000
const double PI = acos(-0);
const int MOD = 1000007;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

using namespace std;
set<LL>jihe;
bool ok(int a,int b,int c)
{
    //这里可以防止重复也可以存的时候sort一下
    return a+b>c && b+c>a && a+c>b
        && a>=b && b>=c && a!=0 && b!=0 && c!=0;
}
int n;
int side[N];
void DFS(int t,int a,int b,int c)
{
    if(t==n)
    {
        if(ok(a,b,c))
        {
            LL p1=M*a+b;
            jihe.insert(p1);
        }
        return;
    }
    a+=side[t];
    DFS(t+1,a,b,c);
    a-=side[t];
    b+=side[t];
    DFS(t+1,a,b,c);
    b-=side[t];
    c+=side[t];
    DFS(t+1,a,b,c);
    c-=side[t];

}
int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        jihe.clear();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&side[i]);
        }
        DFS(0,0,0,0);
        cout<<jihe.size()<<endl;
    }
    return 0;
}
时间: 2024-10-10 20:23:19

10道ACM例题让你三天学会STL的相关文章

【转载】经典10道c/c++语言经典笔试题(含全部所有参考答案)

经典10道c/c++语言经典笔试题(含全部所有参考答案) 1. 下面这段代码的输出是多少(在32位机上). char *p; char *q[20]; char *m[20][20]; int (*n)[10]; struct MyStruct { char dda; double dda1; int type ; }; MyStruct k; printf("%d %d %d %d %d",sizeof(p),sizeof(q),sizeof(m),sizeof(n),sizeof(

面试必备的10道MySQL题

MySQL 事务,是我们去面试中高级开发经常会被问到的问题,很多人虽然经常使用 MySQL,SQL 语句也写得很溜,但是面试的时候,被问到这些问题,总是不知从何说起.下面我们先来了解一下什么是 MySQL事务,再给大家分享10道面试必备的MySQL题. MySQL事务是数据处理的最小操作单元,是一组不可在分割的操作集合,这个操作单元里的一系列操作要么都成功,要么都失败. 1.MySQL主从复制的原理.(1).主库必须开启二进制日志(2).当有增删改的语句时,会记录到主库的binlog中(3).主

10道java经典算法题,每一题都能提升你的java水平!第二弹!

10道java经典算法! 持续更新java小知识,跪求关注,祝关注我的人都:身体健康,财源广进,福如东海,寿比南山,早生贵子,从不掉发! [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去   掉不满足条件的排列. public class Wanshu { public static void main(String[] args) { int i=0; int j=

php学习之道:WSDL详解(三)

通过声明方式定义绑定(binding)属性 如果你在服务中采用SOAP binding,你可以使用JAX-WS来指定一定数量的属性binding.这些属性指定对应你在WSDL中指定的属性.某些设置,比如参数类型,可以约束你实现的方法,这些设置也影响声明的效用. @SOAPBinding声明,定义在javax.jws.soap.SOAPBinding接口中.它提供发布时的SOAP Binding细节.如果@SOAPBinding没有被指定,则用缺省的doc/literal SOAPBinding.

蓝鸥成都整理Java程序员的10道XML面试题

蓝鸥成都给大家整理了10道常见的XML面试问答题,这些问题大部分在Java面试中会问到.XML并不依赖于其他编程语言,同SQL一样是编程人员所需要的技能之一,因此在任何技术工作面试之前准备一些XML问题是很有意义的. XML面试问答 这些问题并不很难但涵盖了XML技术的一些重要领域,比如DTD,XML Schema,XSLT转换,XPATH检索,XML绑定,XML解析器以及XML的基本知识,比如命名空间,校验,属性,元素等. 问题1:XML是什么? 答:XML即可扩展标记语言(Extensibl

10道有关ios的题

1.你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗? 2.你实现过多线程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在线程中创建或者传递?你是用什么样的策略来实现的? 3.Core开头的系列的内容.是否使用过CoreAnimation和CoreGrap

Java程序员的10道XML面试题

如今,面对web开发人员的Java各种面试中,XML面试题在各种编程工作的面试中很常见.XML是一种成熟的技术,经常作为从一个平台到其他平台传输数据的标准.XML面试问题包括用于转换XML文件的XSLT技术,以及XPATH,XQuery等各种XML技术和XML基础知识. 笔者从论坛收集看到常见的XML面试问答题.这些问题大部分在Java面试中会问到,同时在C,C++,Scala或其他语言的编程面试中同样很有用处.作为编程人员所需要的技能之一,在任何技术工作面试之前准备一些XML问题是很有意义的.

10道C++输出易错笔试题收集(敢进来挑战吗?)

下面这些题目都是我之前准备笔试面试过程中积累的,大部分都是知名公司的笔试题,C++基础薄弱的很容易栽进去.我从中选了10道简单的题,C++初学者可以进来挑战下,C++大牛也可以作为娱乐玩下(比如下面的第6题).为了便于大家思考,将题目与答案分开,不过无论题目本身如何,我觉得后面的解析过程更值得学习,因为涉及很多我们学习C++过程中必知必会的小知识点 . 第一部分:题目 如下函数,在32 bit系统foo(2^31-3)的值是:() int foo(int x) { return x&-x; }

10道C++输出易错笔试题收集

下面这些题目都是我之前准备笔试面试过程中积累的,大部分都是知名公司的笔试题,C++基础薄弱的很容易栽进去.我从中选了10道简单的题,C++初学者可以进来挑战下,C++大牛也可以作为娱乐玩下(比如下面的第6题).为了便于大家思考,将题目与答案分开,不过无论题目本身如何,我觉得后面的解析过程更值得学习,因为涉及很多我们学习C++过程中必知必会的小知识点 . 第一部分:题目 如下函数,在32 bit系统foo(2^31-3)的值是:() int foo(int x) { return x&-x; }