2022 年上海市大学生程序设计竞赛 M. My University Is Better Than Yours

大家总喜欢搞些什么排行榜。有一说一,排行榜通常不重要,除非——比如你老板要你做一下年终总 结。

为了实现建设世界一流大学和建设世界一流学科的目标,不少大学都用各种方式提升排名:发表论文、 申请基金、提升多样性. . . 不过看起来这些并不容易,而且 US News 和 Times 这样的机构并不一定会 公正评判你的工作。因此,一些大学更聪明——自己发布排行榜,这可以使得自己的名次间接变好。比 如,通过上海某大学发布的软科排名(ARWU)作为桥梁,咖波甚至可以论证他的闵行理工学院要好于 麻省理工学院:

Zizheng Fang

 

当然,除了咖波的工作面试里,上面这种比较最多出现在知名公众号二月十三里。与此同时,咖波想知 道在这种比较方式下排名会发生什么样的变化。考虑 m 个排行榜中的 n 所大学,为简单起见,所有大 学都用一个从 1 到 n 的数字编号来表示。这里,咖波定义学校 x 直接好于学校 y,当且仅当存在一份 大学排名中学校 x 排在学校 y 前面。如果咖波认为学校 x 好于学校 y,当且仅当存在一个学校的序列 {s1, s2, ..., sk} (k ≥ 2),满足:

• s1 = x, sk = y;

• ∀i ∈ {1, 2, . . . , k − 1}, 学校 si 直接好于学校 si+1。

对于每一所学校,咖波想知道这所学校好于多少所其他学校。

 

 因为附有中文题面,题目大意不再介绍。

解题思路:

一种比较常见的做法就是运用图论的知识,缩点+拓扑。这里要介绍的是一种比较新颖的做法(好吧,其实主要是我自己太懒,不想写那么长的代码)。具体思路如下:

对于每一个榜单,每次从前往后遍历所有榜单的同一个位置,我们会发现一个神奇的事情,如果当前遍历到了第i列(i从1开始,所有榜单的同一个位置构成一列),并且你发现在你遍历这前i列的过程中只出现了i个不同的数,说明什么?,从上次划定的边界开始到当前列,新增的学校只在这部分区域中出现,这些学校一定不会在后面的列中出现了,也就是说这些新增的学校在这部分区域内形成了一个环,说明这些新增的学校有着相同的答案=n-上次划定的边界,至于我们反复提到的边界是啥?当我们遇到上述这种情况的时候,比如说是在第i列遇到了这种情况,那么我们就像边界划为i+1,我们每次将新增的学校放入一个队列中,每次遇到这种情况用队列中的学校编号更新答案,然后将队列清空。

上代码:

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,m;
vector<int>a[N];
bool vis[N];
int ans[N];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int x;
			cin>>x;
			a[i].push_back(x);
		}
	}	
	int num=0;
	queue<int>q;
	for(int i=0,las=1;i<n;i++)
	{
		for(int j=1;j<=m;j++)
		if(!vis[a[j][i]])
		{
			vis[a[j][i]]=1;
			num++;
			q.push(a[j][i]);
		}
		if(num==i+1)//代码中的列是从0开始的,所以是i+1 
		{
			while(q.size())
			{
				int x=q.front();
				q.pop();
				ans[x]=n-las;
			}
			las=num+1;//更新边界 
		 } 
	}
	for(int i=1;i<=n;i++)
	cout<<ans[i]<<" ";
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值