第六章 C++标准模板库介绍
目录
6.1 vector的常见用法
头文件:#include <vector>
和 using namespace std;
6.1.1 vector的定义
如果typename
是STL
容器,则需要在两个>
中间加一个空格,否则可能会被视为移位操作符。
vector<typename> name;
vector<vector<int> > name; //两个维都可变长
vector<typename> arrayname[arraysize]; //一维长度固定为了arraysize
6.1.2 vector内元素的访问
1. 通过下标访问
vi[idx]
2. 通过迭代器访问
v[i]
等价于*(vi.begin()+i)
vector<typename>::iterator it;
6.1.3 vector的常用函数
1. push_back()
时间复杂度:O(1)。
2. pop_back()
时间复杂度:O(1)。
3. size()
时间复杂度:O(1)。
4. clear()
时间复杂度:O(n)。
5. insert()
向vector
的任意 迭代器 it
处插入一个元素x
,时间复杂度O(n)。
insert(it,x);
6. erase()
-
删除单个元素
erase(it)
- 删除迭代器为it
处的元素 -
删除一个区间
[first,last)
内所有的元素
erase(first,last)
-first
和last
为迭代器
6.1.4 例题
【例】A1039 Course List for Student (25 分)
- 由于该题测试点数据量很大,使用stl会超时。所以用hash映射。
- 这道题本身不难,但使用
map
实现名字和index之间的映射就是会超时,只能说在数据量特别大的时候,用map实现的映射反而是一个累赘,这时候,hash实现的直接映射会更快。 - 虽然用了hash,但是巧就巧在将名字单独存储了。排序时只改变下标,会快很多。如果用
string
存储名字,也是可以ac的。 - 在数据量很大的时候,不要用cin和cout,用scanf。
- 在数据量很大的时候,不要用string,用char[]。 麻烦就麻烦在
map
不能用char[]
,所以只能用hash
实现名字和index的映射。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=40010;
const int m=26*26*26*10+10;
vector<int> cour[m];
int getId(char name[])
{
int id=0;
for(int i=0;i<3;i++)
id=id*26+(name[i]-'A');
id=id*10+(name[3]-'0');
return id;
}
int main()
{
char name[5];
int n,k;
scanf("%d %d",&n,&k);
for(int i=0;i<k;i++)
{
int course,x;
scanf("%d %d",&course,&x);
for(int j=0;j<x;j++)
{
scanf("%s",name);
int id=getId(name);
cour[id].push_back(course);
}
}
for(int i=0;i<n;i++)
{
scanf("%s",name);
int id=getId(name);
printf("%s %d",name,cour[id].size());
sort(cour[id].begin(),cour[id].end());
for(int i=0;i<cour[id].size();i++)
{
printf(" %d",cour[id][i]);
}
printf("\n");
}
return 0;
}
23分版本(最后一个点超时)
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
int n,k,stuIdx=1;
struct STU{
string name;
vector<int> course;
}stu[40010];
map<int,string> idxToName;
map<string,int> nameToIdx;
int main()
{
cin>>n>>k;
for(int i=1;i<=k;i++)
{
int idx,cnt;
cin>>idx>>cnt;
for(int j=0;j<cnt;j++)
{
string name;
cin>>name;
if(nameToIdx[name]==0)
{
nameToIdx[name]=stuIdx;
idxToName[stuIdx]=name;
stu[nameToIdx[name]].name=name;
stu[nameToIdx[name]].course.push_back(idx);
stuIdx++;
}
else
{
stu[nameToIdx[name]].course.push_back(idx);
}
}
}
for(int i=1;i<=n;i++)
{
string name;
cin>>name;
if(nameToIdx[name]==0)
cout<<name<<" "<<0<<"\n";
else
{
int theIdx=nameToIdx[name];
sort(stu[theIdx].course.begin(),stu[theIdx].course.end());
cout<<stu[theIdx].name<<" "<<stu[theIdx].course.size();
for(int j=0;j<stu[theIdx].course.size();j++)
cout<<" "<<stu[theIdx].course[j];
cout<<"\n";
}
}
}
【例】A1047 Student List for Course (25 分)
ATTENTION
- C语言的字符串的实质是一个字符数组中存储的字符序列,如果直接比较大小相当于比较了两个字符串的首地址的大小,毫无意义。
strcmp
函数用于比较两个字符串并根据比较结果返回整数。 基本形式为strcmp(char* str1,char* str2)
。若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。- 直接排序字符串会导致多个字符串的移动,所以这里将名字单独存放在
stu
数组中,比较函数比较下标。 - 用cin和cout超时时,先试试把它们改成scanf和prinf。
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=40010;
int n,k,c;
char stu[maxn][5];
vector<int> cou[2510];
bool cmp(int a,int b) {return strcmp(stu[a],stu[b])<0;}
int main()
{
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%s %d",stu[i],&c);
for(int j=0;j<c;j++)
{
int course;
scanf("%d",&course);
cou[course].push_back(i);
}
}
for(int i=1;i<=k;i++)
{
printf("%d %d\n",i,cou[i].size());
sort(cou[i].begin(),cou[i].end(),cmp);
for(int j=0;j<cou[i].size();j++)
printf("%s\n",stu[cou[i][j]]);
}
return 0;
}
其他写法
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//用cin cout 会超时!!!
string stu[40010];
vector<string> course[2510];
int n,k,c;
int main()
{
scanf("%d %d",&n,&k);
for(int i=0;i<n;i++)
{
cin>>stu[i];
scanf("%d",&c);
for(int j=0;j<c;j++)
{
int tmp;
scanf("%d",&tmp);
course[tmp].push_back(stu[i]);
}
}
for(int i=1;i<=k;i++)
{
sort(course[i].begin(),course[i].end());
printf("%d %d\n",i,course[i].size());
for(int j=0;j<course[i].size();j++)
printf("%s\n",course[i][j].c_str());
}
return 0;
}