NEFU 大一寒假训练十三(vector)2020.02.19

Summary

整体来说今天题目的数量和难度还算比较友好的。
另外,发现了一个神奇的汉诺塔,哈哈哈 ヾ(•ω•`)o
在这里插入图片描述

Information

注:AC/Submit 数据 Contest 结束后更新。

No. Title AC/Submit
A 中间数 50/73
B 锯齿矩阵 43/143
C 小明堆积木 31/81
D 上网统计 16/27
E 圆桌问题 11/24
F 钻石收集者-vector 3/5

Problem A: 中间数 (1675) [60/101]

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: 锯齿矩阵 (pid) [60/101]

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: 小明堆积木 (pid) [60/101]

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: 上网统计 (pid) [60/101]

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: 圆桌问题 (pid) [60/101]

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 (pid) [60/101]

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;
}
发布了66 篇原创文章 · 获赞 218 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/csg999/article/details/104390327