Summary
整体来说今天题目的数量和难度还算比较友好的。
另外,发现了一个神奇的汉诺塔,哈哈哈 ヾ(•ω•`)o
Information
No. | Title | AC/Submit |
---|---|---|
A | 中间数-vector | 55/82 |
B | 锯齿矩阵-vector | 46/182 |
C | 小明堆积木-vector | 45/107 |
D | 上网统计-vector/map | 30/72 |
E | 圆桌问题-vector | 24/54 |
F | 钻石收集者-vector | 8/20 |
Problem A: 中间数 (1675) [55/82]
Tips
很简单的一个 vector,算是个签到题吧。
如果是奇数个就输出最中间的那个数;否则,输出中间两个数的和。
结果最开始我偶数个的时候输出了中间两个数加和除2,人都傻了。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<long long>v;
long long ans,num;
while(cin>>num&&num!=0)v.push_back(num);
if(v.size()==0)
{
cout<<0;
return 0;
}
if(v.size()%2==0)ans=v[v.size()/2]+v[v.size()/2-1];
else ans=v[v.size()/2];
cout<<ans;
return 0;
}
Problem B: 锯齿矩阵 (2128) [46/182]
Tips
这题也不难,按照要求依次放数就行了。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v[10000];
int n,m,x,y;
while(~scanf("%d %d",&n,&m))
{
for(int i=0;i<n;i++)
{
v[i].clear();
}
while(m--)
{
scanf("%d %d",&x,&y);
v[x-1].push_back(y);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<v[i].size();j++)
{
if(j!=0)printf(" ");
printf("%d",v[i][j]);
}
printf("\n");
}
}
return 0;
}
Problem C: 小明堆积木 (2129) [45/107]
Tips
按要求移动积木即可,开 vector 数组比较方便。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v[100000];
int n,m,a,b;
while(~scanf("%d %d",&n,&m))
{
for(int i=0;i<n;i++)
{
v[i].clear();
v[i].push_back(i+1);
}
while(m--)
{
scanf("%d %d",&a,&b);
if(a==b||v[b-1].size()==0)continue;
for(int i=0;i<v[b-1].size();i++)
{
v[a-1].push_back(v[b-1][i]);
}
v[b-1].clear();
}
for(int i=0;i<n;i++)
{
if(v[i].size()==0)printf("-1");
for(int j=0;j<v[i].size();j++)
{
if(j!=0)printf(" ");
printf("%d",v[i][j]);
}
printf("\n");
}
}
return 0;
}
Problem D: 上网统计 (1676) [30/72]
Tips
直接把名字放数组第一个输出的时候可以方便一些。
可以用 map 存放 用户->数组下标 的映射,查找的时候能快一些。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<string>v[1001];
map<string,int>ma;
int n,m;
string a,b;
while(~scanf("%d %d",&n,&m))
{
ma.clear();
for(int i=1;i<=n;i++)v[i].clear();
while(m--)
{
cin>>a>>b;
if(ma.count(a))v[ma[a]].push_back(b);
else
{
ma[a]=ma.size();
v[ma[a]].push_back(a);
v[ma[a]].push_back(b);
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<v[i].size();j++)
{
if(j!=0)printf(" ");
cout<<v[i][j];
}
printf("\n");
}
}
return 0;
}
Problem E: 圆桌问题 (2127) [24/54]
Tips
先将 2n 个人存入 vector,之后去掉坏人,留下的就是好人的编号了。
最开始直接依次报数结果 TLE 了,之后发现只需要处理数组下标就知道删谁了。
最后根据数组里的好人输出 B和G。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>v;
int n,m,cnt,pos;
while(~scanf("%d %d",&n,&m))
{
v.clear();
for(int i=0;i<2*n;i++)
{
v.push_back(i+1);
}
pos=0;
while(v.size()!=n)
{
pos+=m-1;
pos%=v.size();
v.erase(v.begin()+pos);
}
cnt=0;
for(int i=0;i<v.size();i++)
{
for(int j=0;j<v[i]-cnt-1;j++)
{
printf("B");
}
cnt=v[i];
printf("G");
}
for(int j=0;j<2*n-cnt;j++)
{
printf("B");
}
printf("\n");
}
return 0;
}
Problem F: 钻石收集者-vector (2124) [8/20]
Tips
可以用桶排序将不同大小宝石依次归类,然后设置一个长度为 k 的区间。
区间依次向右移动,同时减去左边的钻石数,加上右边的钻石数,找到所有区间中的最大值即可。
PS:本人十分好奇那些大小为 0 的钻石长啥样。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
int bucket[100001]={0};
int n,k,tmp,max=-1,l,r,sum=0;
scanf("%d %d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&tmp);
bucket[tmp]++;
}
l=0;r=k;
for(int i=0;i<=k;i++)sum+=bucket[i]; //区间加和
max=sum;
while(r+1<100000) //区间依次右移
{
sum-=bucket[l];
sum+=bucket[r+1];
l++;
r++;
if(sum>max)max=sum;
}
printf("%d",max);
return 0;
}