2020年2月19日 vector
vector的意思就是向量,在使用时可以看成最大大小为2e9的且大小可变的数组。更多详细内容可见大佬的vector解析。
今天的题难度比较亲民,但每道题都有点值得重视的地方。
林大OJ 1675 中间数
签到题。。看清楚输出什么,一开始输出的中间两数的平均数,人都傻了。
#include <bits/stdc++.h>
using namespace std;
vector<int>a;
int main()
{
int n,x;
while(cin>>x&&x){
a.push_back(x);
}
n=a.size();
if(n%2==0){
printf("%d\n",a[n/2]+a[n/2-1]);
}
else
printf("%d\n",a[(n-1)/2]);
return 0;
}
林大OJ 2128 锯齿矩阵
相当于利用vector开了一个二维数组,只不过比普通的二维数组更容易操作,且可以分别操作。还有就是注意输出空行和清空vector(多组输入)。
#include <bits/stdc++.h>
using namespace std;
int n,m,x,y;
vector<int>a[10001];
int main()
{
ios::sync_with_stdio(false);
while(cin>>n>>m){
while(m--){
cin>>x>>y;
a[x].push_back(y);
}
for(int i=1;i<=n;i++){
for(int j=0;j<a[i].size();j++)
j==a[i].size()-1?printf("%d\n",a[i][j]):printf("%d ",a[i][j]);
if(a[i].size()==0) printf("\n")
a[i].clear();
}
}
return 0;
}
林大OJ 2129 小明堆积木
没什么太难的地方,看懂题目一步一步走下来就行,开头先清空再赋初值的操作是真的点睛之笔。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int>vis[N];
int main()
{
ios::sync_with_stdio(false);
int n,m,a,b;
while(cin>>n>>m){
for(int i=1;i<=n;i++){
vis[i].clear();
vis[i].push_back(i);
}
while(m--){
cin>>a>>b;
if(vis[b].size()==0||a==b) continue;
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]);
}
}
}
return 0;
}
林大OJ 1676 上网统计
做法来自上课时jwGG的提示,用vector存放各自的节目,用两个map完成序号与名字的对应。小心对应时别搞混了。
还有就是输出字符串时要加.c_str(),不知道为什么,加上就对了。
#include <bits/stdc++.h>
using namespace std;
map<string,int>a;//记录用户名对应的序号
map<int,string>b;//记录序号对应的用户名
vector<string>vis[1010];//vis[i][j]表示序号为i的用户浏览的第j个网站
int n,m,cnt,t;
string id,web;
int main()
{
ios::sync_with_stdio(false);
a.clear();
cin>>n>>m;
while(m--){
cin>>id>>web;
if(a[id]==0){//此时输入的id没有出现过
a[id]=++cnt;//给该用户名编号(从1开始)
vis[cnt].push_back(web);//保存到cnt编号下的网站记录中
b[cnt]=id;//保存该编号对应的用户名
}
else{//此时输入的id已经出现过了
t=a[id];//找到该id对应的编号
vis[t].push_back(web);//存进去
}
}
for(int i=1;i<=cnt;i++){
printf("%s ",b[i].c_str());//输出第i个编号对应的id
for(int j=0;j<vis[i].size();j++)//输出这个id对应的所有网站
j==vis[i].size()-1?printf("%s\n",vis[i][j].c_str()):printf("%s ",vis[i][j].c_str());
}
return 0;
}
林大OJ 2127 圆桌问题
比较经典的报数问题,还有处死是什么鬼,也太狠了吧。
这道题的核心在于确定被淘汰的人的序号,是难点,也是最关键的点。
#include <bits/stdc++.h>
using namespace std;
vector<int>a;
int n,m;
int main()
{
ios::sync_with_stdio(false);
while(cin>>n>>m){
a.clear();
for(int i=0;i<2*n;i++)//从0开始放人
a.push_back(i);
int pos=0;
for(int i=0;i<n;i++){//淘汰n个人
pos=(pos+m-1)%a.size();//被淘汰的人在vector中的下标(vector的长度在变化)
a.erase(a.begin()+pos);
}
int p=0;
for(int i=0;i<2*n;i++){
if(i==a[p]&&p<n){//现在未被淘汰的人在vector中的值与其序号相等,被淘汰的人值为0;
p++;
printf("G");
}
else printf("B");
}
printf("\n");
}
return 0;
}
林大OJ 2124 钻石收集者-vector
被自己的思路限制到了,看了题解以后豁然开朗。以下是题解:
桶排序的思想,记录x出现的次数,存放到cnt[x]里,然后求cnt数组的前缀和,遍历一次前缀和数组取[i,i+k]区间的最大值,即答案为:max(sum[i+k]−sum[i−1]),i∈[0,N−k] max(sum[i+k]-sum[i-1]),i∈[0,N-k]max(sum[i+k]−sum[i−1]),i∈[0,N−k]。
此处i=0时需要特判,否则容易出问题。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5;
int n,k,x,mx,cnt[N+10],sum[N+10];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>x;
cnt[x]++;
}
for(int i=0;i<=N;i++){
if(i==0) sum[i]=cnt[i];
else sum[i]=sum[i-1]+cnt[i];
}
for(int i=0;i+k<=N;i++){
if(i==0) mx=sum[i+k];
else mx=max(mx,sum[i+k]-sum[i-1]);
}
printf("%d\n",mx);
return 0;
}