vector直接翻译为“向量”,一般说成“变长数组”,也即“长度根据需要而自动改变的数组。
在竞赛中,有些题目需要定义很大的数组,这样会出现“超出内存限制”的错误。比如,如果一个图的顶点太多,使用邻接矩阵就会超出内存限制,使用指针实现邻接表又很容易出错,而使用vector实现简洁方便,还可以节省存储空间。
使用vector,首先需要添加vector头文件,即#include ,同时,必须要有“using namespace std”。
定义一个 vector 的方法如下:
vector< typename > name;
以上定义相当于定义了一个一维数组name[size],只是
size不确定,其长度可以根据需要而变化。其中typename可以是任何基本类型,例如int、double、char、结构体等,也可以是STL标准容器,例如vector、queue等
访问 vector 中的元素一般有两种方式。
第一种是通过“下标”访问。
例如,对于容器 vector< int > v,可以使用 v[index]来访问它的第 index 个元素。其中,0≤index≤v.size()-1,v.size()表示 vector 中元素的个数。
第二种方式是通过“迭代器”访问。
可以将迭代器(iterator)理解为一种类似指针的变量。其定义为:
vector< typename >::iterator it;
例如:
vector< int >::iterator it= v.begin();
for(int i = 0; i <= 5; i++)
printf("%d ",*(it + i));
常用函数:
(1)vis.push_back()
push_back(x)用来在 vector 后面添加一个元素 x,时间复杂度为 0(1)。
(2)vis.size()
如果是一维数组,size()用来获得 vector 中元素的个数;如果是二维数组,size()用来获得vector 中第二维的元素个数,时间复杂度为 0 (1)。
(3)vis.pop_back()
pop_back()用来删除 vector 的尾元素,时间复杂度为 0(1)。
(4)vis.clear()
clear()用来清空 vector 中的所有元素,时间复杂度为 0(n),其中 n 为 vector 中元素的个数。
(5)vis.insert ()
insert(it,x)用来向 vector 任意迭代器 it 处插入一个元素 x,时间复杂度为 0(n)。
(6)vis.erase()
erase()用来删除 vector 中的元素,有两种用法。一种是 erase(it),删除迭代器 it 处的元素;另一种是 erase(first,last),删除左闭右开区间[first,last)内的所有元素。
中间数
#include <bits/stdc++.h>
using namespace std;
vector<int>vis;
int x;
int main()
{
while(cin>>x&&x)
{
vis.push_back(x);
}
int l=vis.size();
if(l%2!=0)//找到目标位置就好了
cout<<vis[(l+1)/2-1]<<endl;
else
cout<<vis[l/2]+vis[l/2-1]<<endl;
return 0;
}
锯齿矩阵
#include <bits/stdc++.h>
using namespace std;
vector<int>vis[10005];
int n,m,x,y;
int main()
{
while(cin>>n>>m)
{
while(m--)
{
cin>>x>>y;
vis[x].push_back(y);
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<vis[i].size();j++)
j==vis[i].size()-1?printf("%d",vis[i][j]):printf("%d ",vis[i][j]);
printf("\n");//这个放在外面,保证没有数是能输出空行
vis[i].clear();
}
}
return 0;
}
小明堆积木
#include <bits/stdc++.h>
using namespace std;
vector<int>vis[100005];
int n,m,a,b;
int main()
{
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
vis[i].push_back(i);
while(m--)
{
cin>>a>>b;
if(a==b||vis[b].size()==0) continue;//这里不能是break,否则OLE
else
{
for(int i=0;i<vis[b].size();i++)
vis[a].push_back(vis[b][i]);
vis[b].clear();
}
}
for(int i=1;i<=n;i++)
{
if(vis[i].size()==0)
printf("-1\n");
else
{
for(int j=0;j<vis[i].size();j++)
j==vis[i].size()-1?printf("%d\n",vis[i][j]):printf("%d ",vis[i][j]);
vis[i].clear();
}
}
}
return 0;
}
上网统计
这题亏大了,不过也怨我自己
#include <bits/stdc++.h>
using namespace std;
vector<string>vis[1005];//记录每个用户浏览的网页,vis[i][j]指第i个用户第j次浏览的网页
map<string,int>a;//按出现顺序记录每个用户的编号,同时最为判断用户是否为第一次出现的依据
map<int,string>b;//记录按顺序的编号对应的用户
int n,m,tmp;
string name,net;
int main()
{
cin>>n>>m;
int ans=0;
while(m--)
{
cin>>name>>net;
if(a[name]==0)//该用户以前没有出现过
{
ans++;
a[name]=ans;
b[ans]=name;
vis[ans].push_back(net);
}
else//出现过
{
tmp=a[name];
vis[tmp].push_back(net);
}
}
for(int i=1;i<=n;i++)
{
cout<<b[i]<<" ";
for(int j=0;j<vis[i].size();j++)
{
j==vis[i].size()-1?printf("%s\n",vis[i][j].c_str()):printf("%s ",vis[i][j].c_str());//注意这里的字符串输出要加.c_str()的后缀,否则无法正常输出,就因为这里忘记了,导致本地都过不去
}
}
return 0;
}
圆桌问题
这是约瑟夫问题,可以用vector模拟
#include <bits/stdc++.h>
using namespace std;
vector<int>vis;
int n,m,a[20005];
int main()
{
while(cin>>n>>m)
{
vis.clear();
memset(a,0,sizeof(a));
for(int i=0;i<2*n;i++)
vis.push_back(i);//初始化
int pos=0;//记录当前位置
for(int i=0;i<n;i++)//处死n个人
{
pos=(pos+m-1)%vis.size();//取余处理
a[vis[pos]]=1;//标记坏人
vis.erase(vis.begin()+pos);处死坏人,数量减一
}
for(int i=0;i<2*n;i++)
{
if(a[i]) printf("B");
else printf("G");
}
printf("\n");
}
return 0;
}
钻石收集者-vector
这题可以不用vector
#include <bits/stdc++.h>
using namespace std;
const int N=1e5;
int sum[N+10],a[N+10];
int n,k,x,most;
int main()
{
cin>>n>>k;
while(n--)
{
cin>>x;
a[x]++;
}
sum[-1]=0;
for(int i=0;i<=N;i++)
sum[i]=sum[i-1]+a[i];
for(int i=0;i+k<=N;i++)
most=max(most,sum[i+k]-sum[i-1]);
cout<<most<<endl;
return 0;
}
这道题,我一开始一直纠结一个问题,就是最后的循环是不是循环到读入的最大值就可以,也就是这样
#include <bits/stdc++.h>
using namespace std;
const int N=1e5;
int sum[N+10],a[N+10];
int n,k,x,maxn;
int main()
{
cin>>n>>k;
while(n--)
{
cin>>x;
if(x>maxn)
maxn=x;
a[x]++;
}
sum[-1]=0;
for(int i=0;i<=maxn+k;i++)
sum[i]=sum[i-1]+a[i];
int mx=0;
for(int i=0;i+k<=maxn;i++)
{
// printf("i+k=%d sum[i+k]=%d\n",i+k,sum[i+k]);
mx=max(mx,sum[i+k]-sum[i-1]);
}
printf("%d\n",mx);
return 0;
}
但是这样是错误的,因为这样的话,有可能会出现无法循环的情况,比如数据
5 3
1 1 1 1 1
这就会直接输出0,因为这组数据的maxn是1,i+k直接比他大了,无法循环
因此循环的最大范围应该是maxn+k即
#include <bits/stdc++.h>
using namespace std;
const int N=1e5;
int sum[N+10],a[N+10];
int n,k,x,maxn;
int main()
{
cin>>n>>k;
while(n--)
{
cin>>x;
if(x>maxn)
maxn=x;
a[x]++;
}
sum[-1]=0;
for(int i=0;i<=maxn+k;i++)//这里前缀和计算到maxn+k
sum[i]=sum[i-1]+a[i];
int mx=0;
for(int i=0;i<=maxn;i++)//i循环到maxn,i+k也就是循环到maxn+k
{
// printf("i+k=%d sum[i+k]=%d\n",i+k,sum[i+k]);
mx=max(mx,sum[i+k]-sum[i-1]);
}
printf("%d\n",mx);
return 0;
}
以前学过的东西记得还是不够扎实,需要常复习复习。。。。。。