【2021天梯赛】L2-L3补题记录

文章检索器

    • 赛后感想
    • 赛后补题
      • Problem 1 L2-038 病毒溯源(25)
      • Problem 2 L2-037 包装机(25)
      • Problem 3 L2-039 清点代码库(25)
      • Problem 4 L2-040 哲哲打游戏(25)

赛后感想

据说今年的天梯赛比以往简单,咱也不知道,没啥感觉,第一次参加天梯赛,所以并不晓得以往正式赛难度如何,反正我这次是失败告终了,难受啊,本来拿个个人三等应该是势在必得的,遇到病毒之后惨了,强行卡了一个多小时,斩获0分。哎,,不说了,都是辛酸泪啊。。。菜鸡流泪。

赛后补题

那就先来解决病毒溯源这个毒瘤吧。
看清题目,看清题目,看清题目。。。
ps:如果长链不唯一,输出最小序列

Problem 1 L2-038 病毒溯源(25)

补题传送门
【2021天梯赛】L2-L3补题记录_第1张图片
【2021天梯赛】L2-L3补题记录_第2张图片
【2021天梯赛】L2-L3补题记录_第3张图片
解题思路:
就是直接暴力的思路。病毒源只有一个,可以记录顶点的度数来寻找病毒源。找到病毒源之后,用 B F S BFS BFS 求一个单源最长路即可。用 f a [ i ] fa[i] fa[i]数组来记录第 i i i 个节点的父亲节点。根据父亲节点与子节点之间的关系,逆向寻找路径,用二维 v e c t o r vector vector 数组记录所有可行方案,再来个排序输出第一个即为最终答案。

C++ AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> v[10010];
int d[10010], dist[10010], fa[10010];
vector<vector<int> > res;
int ans, root;
bool vis[10010];
void bfs()
{
     
	queue<int> q;
	q.push(root);
	dist[root] = 1;
	while (q.size())
	{
     
		int u = q.front();q.pop();
		for (int i = 0;i < v[u].size();i++)
		{
     
			int j = v[u][i];
			if (dist[j] < dist[u] + 1)
			{
     
				dist[j] = dist[u] + 1;
				fa[j] = u;
				q.push(j);
			}
		}
	}
}
bool cmp(vector<int> x, vector<int> y)
{
     
	for (int i = 0;i < x.size();i++)
	{
     
		if (x[i] != y[i]) return x[i] < y[i];
	}
}
int main()
{
     
	int n; scanf("%d", &n);
	for (int i = 0;i < n;i++)
	{
     
		int k; scanf("%d", &k);
		d[i]++;
		for (int j = 0;j < k;j++)
		{
     
			int x; scanf("%d", &x);
			v[i].push_back(x);
			d[x]++;
		}
	}
	while (d[root] != 1) root++;
	bfs();
	fa[root] = root;
	int pos;
	for (int i = 0;i < n;i++)
	{
     
		ans = max(ans, dist[i]);
	}
	printf("%d\n", ans);
	for (int i = 0;i < n;i++)
	{
     
		if (dist[i] == ans)
		{
     
			vector<int> tmp;
			int rt = i;
			while (fa[rt] != rt)
			{
     
				tmp.push_back(rt);
				rt = fa[rt];
			}
			tmp.push_back(root);
			reverse(tmp.begin(), tmp.end());
			res.push_back(tmp);
		}
	}
	sort(res.begin(), res.end(), cmp);
	for (int i = 0;i < res[0].size();i++)
	{
     
		printf("%d", res[0][i]);
		if (i < res[0].size() - 1) printf(" ");
	}
	return 0;
}

Problem 2 L2-037 包装机(25)

补题传送门
这个题是个简单的队列与栈的操作,不做过多解释,直接放上我的代码吧。

C++ AC代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
queue<char> q[110];
int op[100010];
char st[110];//框
int s;
int main()
{
     
	int N, M, S; cin >> N >> M >> S;
	for (int i = 1;i <= N;i++)
	{
     
		string str; cin >> str;
		for (int j = 0;j < str.size();j++) q[i].push(str[j]);
	}
	M = 0;
	while (1)
	{
     
		int x; cin >> x;
		if (x == -1) break;
		op[++M] = x;
	}
	vector<char> res;//传送带上物品
	for (int i = 1;i <= M;i++)
	{
     
		int k = op[i];
		if (k == 0)
		{
     
			if (s) res.push_back(st[s--]);
		}
		else {
     
			if (q[k].empty()) continue;
			if (s < S){
     
				st[++s] = q[k].front();q[k].pop();
			}
			else {
     
				res.push_back(st[s--]);
				st[++s] = q[k].front();q[k].pop();
			}
		}
	}
	for (int i = 0;i < res.size();i++)
	{
     
		cout << res[i];
	}
	return 0;
}

Problem 3 L2-039 清点代码库(25)

补题传送门
【2021天梯赛】L2-L3补题记录_第4张图片
【2021天梯赛】L2-L3补题记录_第5张图片
解题思路:
这个题还真就长见识了,两个 v e c t o r vector vector 容器可以直接比较大小,比较规则是从前往后遍历每一个元素,返回第一个不相等的元素的比较结果。可以放进 s e t set set 中,也可以放进 m a p map map 中。这样的话,就很好操做了。一开始我使用 m a p map map 记录出现的次数,利用 s e t set set 去重,但可能是卡 m a p map map 了,只能得到 21 21 21 分。得到满分的做法是先排序,相同的就会在相邻的位置,从前往后遍历,记录出现次数,用结构体存储可以比较方便的实现排序及计数。
注意:这个题会卡 c i n cin cin c o u t cout cout.

C++ Score 25:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<vector<int> > v;
struct node {
     
	int sum;
	vector<int> tmp;
}st[10010];
int s;
bool cmp(node x, node y)
{
     
	if (x.sum != y.sum) return x.sum > y.sum;
	else return x.tmp < y.tmp;
}
int main()
{
     
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 0;i < n;i++)
	{
     
		vector<int> tmp;
		for (int j = 0;j < m;j++)
		{
     
			int x; scanf("%d", &x);
			tmp.push_back(x);
		}
		v.push_back(tmp);
	}
	sort(v.begin(), v.end());
	st[++s] = {
      1,v[0] };
	for (int i = 1;i < n;i++)
	{
     
		if (v[i] != v[i - 1])
		{
     
			st[++s] = {
      1,v[i] };
		}
		else st[s].sum++;
	}
	sort(st + 1, st + s + 1, cmp);
	printf("%d\n", s);
	for (int i = 1;i <= s;i++)
	{
     
		printf("%d", st[i].sum);
		for (int j = 0;j < st[i].tmp.size();j++)
		{
     
			printf(" %d", st[i].tmp[j]);
		}
		if (i < s) printf("\n");
	}
	return 0;
}

C++ Score 21:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> v[10010];
map<vector<int>, int> mp;
set<vector<int> > s;
bool cmp(vector<int> x, vector<int> y)
{
     
	if (mp[x] != mp[y]) return mp[x] > mp[y];
	return x < y;
}
int main()
{
     
	int n, m; scanf("%d%d",&n,&m);
	for (int i = 0;i < n;i++)
	{
     
		for (int j = 0;j < m;j++)
		{
     
			int x; scanf("%d",&x);
			v[i].push_back(x);
		}
		mp[v[i]]++;
		s.insert(v[i]);
	}
	vector<vector<int> > res;
	for (auto item : s) {
     
		res.push_back(item);
	}
	sort(res.begin(), res.end(), cmp);
	/*for (int i = 0;i < res.size();i++)
	{
		for (int j = 0;j < res[i].size();j++)
		{
			cout << res[i][j] << " ";
		}
		cout << endl;
	}*/
	printf("%d\n",res.size());
	for (int i = 0;i < res.size();i++)
	{
     
		printf("%d",mp[res[i]]);
		for (int j = 0;j < res[i].size();j++)
		{
     
			printf(" %d",res[i][j]);
		}
		if (i < res.size() - 1) printf("\n");
	}
	return 0;
}

Problem 4 L2-040 哲哲打游戏(25)

补题传送门
阅读理解题,按照题目描述模拟就OK,so easy 呀。无语了,当时就应该先开这个题的,策略问题,当时看到题目描述有点长,就习惯性的略古了,直接留到了后面,然而到后面之后根本没心思冷静下来读题,难受。

C++ Score 25:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 100010;
vector<int> v[N];
int mark[N];
int main()
{
     
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 1;i <= n;i++)
	{
     
		int k; scanf("%d", &k);
		v[i].push_back(0);
		for (int j = 1;j <= k;j++)
		{
     
			int x;scanf("%d", &x);
			v[i].push_back(x);
		}
	}
	int now = 1;
	while (m--)
	{
     
		int op, x; scanf("%d%d", &op, &x);
		if (op == 1)
		{
     
			mark[x] = now;
			printf("%d\n",mark[x]);
		}
		else if(op == 0){
     
			now = v[now][x];
		}
		else if (op == 2)
		{
     
			now = mark[x];
		}
	}
	printf("%d", now);
	return 0;
}

L2补题完毕。
L3明天继续。。。

你可能感兴趣的:(天梯赛)