ACM总结(STL)
今周总结一下STL的有关内容。因为STL在cf上或是在平常一些竞赛中经常可以被找到,一般以第一,二题的形式出现。而且竞赛中很多常用的数据结构、算法在STL中都有熟练地掌握它们可以极大的简化编程,它可以说是竞赛的信心来源因为,掌握它们一般可以快速的ac第一二(水题)道题。
- Vector(动态数组)
头文件:#include <vector>
定义:vector<type>s; //type数据类型,如int,char,string
s.push_back(k)//在数据尾插入值为k的元素
s.clear()//清空
s.insert(s.begin()+i,k)//在第i个元素前面插入k
s.erase(s.begin()+k)//删除第k+1个元素
s.erase(s.begin()+i,s.begin()+j)//删除区间[i,j-1]中所有元素
s.pop_back()//删除末尾元素
int size=s.size()//元素个数
运用示例
设计程序
将k个数中的奇数或偶数分别输出
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
int main()
{ vector<int>a;
cin>>n;
int k;
a.clear();
for(int q=0; q<n; q++)
{ cin>>k;
a.push_back(k);
}
for(int q=0; q<a.size();)
{ if(a[q]%2==0)
{
q++; // 注意:vector插入或删除中间某一项时这个元素后面的所有元素往后或往前移
}
else
{a.erase(a.begin()+q);
}
}
sort(a.begin(),a.end());
for(int q=0; q<a.size(); q++)
{
cout<<a[q]<<" ";
}
return 0;
}
- 栈(stack)
特点:先进后出
头文件:#include<stack>
定义:stack<type>s;//type数据类型,如int,char,string
s.push(k)//把k放到栈顶
s.top()//返回栈顶的元素
s.pop()//删除栈顶的元素
s.size()//返回栈中元素个数
s.empty()//检查元素是否为空,if为空,返回true,else返回false;
运用示例
翻转字符串(来自hdu 1062)
输入:“olleh !dlrow”
输出:“hello world!”
#include<iostream>
#include<algorithm>
#include<stack>
#include<cmath>
#include<stdio.h>
using namespace std;
int n;
char ch;
stack<char>a;
int main()
{cin>>n;
getchar();
while(n--)
{while(1)
{scanf("%c",&ch);//相当于ch=getchar()但是不能用cin>>因为cin不支持录入空格与回车键
//其实cin,scanf与getchar()都有缓冲区
//scanf只有在scanf("%c",&ch)的情况下才支持空格与回车键
if(ch==' '||ch=='\n'||ch==EOF)
{while(!a.empty())
{cout<<a.top();
a.pop();
}
if(ch==' ')
cout<<" ";
}
else
{a.push(ch);}
if(ch=='\n'||ch==EOF)
{break;}
}
cout<<endl;
}
return 0;
}
注:cin,scanf与getchar()都有缓冲区
这个是做题时看一些竞赛选手写的代码时,发现的当时看见感到很诧异,可以看看下面的代码
#include<iostream>
using namespace std;
int main()
{ int n,a;
cin>>n;
for(int q=0;q<n;q++)
{cin>>a;
if(a%2==0)
{cout<<a<<" ";}
}
return 0;
}
是不是会营造一种边输入边输出的感觉!
- 优先队列(priority_queue)
头文件:#include<queue>
特点 : 顾名思义就是优先级最高的先出列,它是队列和排序的完美结合,不仅可以储存数据,还可以按照设定的规则进行排序。(用重载运算符对运算符重新定义),注意每次的push和pop操作,优先数列都会动态调整,把优先级最高的元素或按照设定的规则放在最前面。
struct node
{
int x;
int y;
};
priority_queue<node>q[5];//定义结构体类型的优先队列
bool operator <(const node &a,const node &b)//重载<运算符,指定优先规则
{
if(a.x==b.x)//如果x相同,y由小到大
return a.y>b.y;
else
return a.x<b.x;//x由大到小
}
- Map
头文件:#include<map>
定义:map<type1,type2>s://type1是对map下标类型的定义,type2是对map元素的定义。
(例如:map<string,int>students;)可以同时储存学生的name与成绩(学号,排名等等)可以看做是一个拥有两个元素类型的结构体,但是map数组可以根据下标对数据精准查询,而结构体要搜索所有的元素,复杂度高效率低。
Student[“yjj”]=99;
5.去重函数(unique)
特点:将相邻的元素进行去重。
对于去重函数(unique),我一直有一个疑问就是,上课听课时好像讲的对于去重后的数,系统自动放到数组(队列)末,但是通过在cf上做题,我发现好像并没有将去重后的元素放到队列末,而是将排序后的元素放在了队列末。
例如:
输入:10
4 5 6 7 7 3 5 5 8 3
对该数组a[10]进行去重。
排序完是:3 3 4 5 5 5 6 7 7 8
而去重完是:3 4 5 6 7 8
若是放到队列末全部输出是:3 4 5 6 7 8 (3 5 5 7 )
而实际是:3 4 5 6 7 8 (6 7 7 8)和排序完的数组末一致
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{ return a>b;
}
int main()
{
int n,t;
cin>>n;
int a[100];
for(int q=0; q<n; q++)
{ cin>>a[q];
}
sort(a,a+n,cmp); //去重前先进行排序。
t=unique(a,a+n)-a;
for(int q=0; q<t; q++)
{
cout<<a[q]<<" ";
}
return 0;
}
6.全排列(next_permutation())
特点:可以按照字典序依次生成元素排列的所有组合。
如:char[3]={a,b,c};
next_permutation()可以按字典序返回6个组合abc,acb,bac,bca,cab,cba。
本来该函数在之前无论是做题还是看书都不曾遇见过,但是在上次海理工大学第二届“联想杯”全国程序设计邀请赛上遇到过一次,但是突然想起了这个函数就试着用了,就ac了。
这是全排列用法:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int a[1000],n;
int main()
{ while(cin>>n)
{memset(a,0,sizeof(a));
for(int q=0;q<n;q++)
{cin>>a[q];}
sort(a,a+n);
while(next_permutation(a,a+n))
{for(int q=0;q<n;q++)
{cout<<a[q];}
cout<<endl;
}
}
return 0;
}
这是该题的代码:
#include<iostream>
#include<algorithm>
using namespace std;
long long n,a[9],b[9],c[100000];
int main()
{ cin>>n;
for(int q=0; q<n; q++)
{ cin>>a[q];
}
for(int q=0; q<n; q++)
{ cin>>b[q];
}
sort(b,b+n);
int l=0;
while(next_permutation(b,b+n))
{ for(int q=0; q<n; q++)
{ if(__gcd(a[q],b[q])>1)
c[l]++;
}
l++;
}
sort(c,c+l);
cout<<c[l-1]<<endl;
return 0;
}
//①__gcd(a,b)a,b的最大公约数。
7.Upper_bound和lower_bound
这个在上一篇博客里详细提到了。