2024年4月24日-暑期实习-第二题(200分)-塔子哥的足球队

在线评测链接

题目描述

\qquad 话说塔子哥带ACM队已经征战沙场多年,又又又又是时候拓展业务面了,你猜怎么着,当上足球领队了,现在正在进行紧张的备赛,冲击篮球杯金牌。

\qquad 塔子哥的足球队一共有 n n n个队员,塔子哥安排他们参与 m m m次点球射门,每次射中用 1 1 1表示,射失(没射中)用 0 0 0表示,塔子哥为他的球员能力强弱拟定了如下标准:

\qquad (1)进球总数更多的队员射门能力更强;

\qquad (2)若进球总数一样多,则比较最多一次连续进的个数,更多的队员能力更强;

\qquad (3)若最多一次连续进球个数一样多,则比较第一次射失的先后顺序,其中后射失的队员更强,若第一次射失顺序相同,则按继续比较第二次射失的顺序,后丢球的队员能力更强,依次类推;

\qquad (4)若前3个规则排序后还能力相等,则队员编号更小的能力更强。

输入描述

\qquad 第一行输入两个整数 n n n m m m,分别表示足球队中队员的数量,以及射门训练的次数。(队员编号从1开始,依次递增) 2 n − 1 2^n-1 2n1个整数,表示整棵满二叉搜索树。其中 1 ≤ n ≤ 10 1 \le n \le 10 1n10,整数之间用空格分割。

\qquad 第二行,第 1 1 1~ n n n个队员从第 1 1 1 m m m次训练的进球情况,每个队员进球情况为连续的 1 1 1 0 0 0的组合,不同队员的情况用空格分隔

\qquad 规定:所有 n n n m m m均为整数 1 ≤ n , m ≤ 1000 1 \le n, m \le 1000 1n,m1000

输出描述

\qquad 所有球员射门能力从强到弱的队员编号,用空格分隔每个编号

样例一

输入

4 5
11100 00111 10111 01111

输出

4 3 1 2

解释

4个队员,射门训练5次,队员3和4进球数均为4个,比队员1H和2的3个更多,队员3连续进球故最多一次为3个,而队员4最大为4。因此队员4射门能力强于队员3,另外队员2比队员1先丢球,因此队员1射门能力强于队员2,顺序为4 3 1 2。

样例二

输入

2 10
1011100111 1011101101

输出

2 1

解释

2个队员,射门训练10次,两个队员的进球总数均为7个,连续进球最多的均为3个,且第前两次丢球顺序均为第2次和第6次训练射门,而队员2第三次丢球为第9次训练,队员1为第7次训练,因此队员2的射门能力强于队员1,顺序为2 1

Limitation

1s, 1024KiB for each test case.

思路

自定义排序实现。

本质就是一个自定义的实现。

  • 第一关键字是每个字符串中 1 的数量,从大到小

  • 第二关键字是每个字符串中最长的连续 1 的数量,从大到小

  • 第三关键字:

    • 此时两个比较的串 A 和 B 中 0 的索引数量必然相同,假设数量为 k
    • 依次比较两个串中的第一个为 0 的索引,第二个为 0 的索引,… ,第 k 个为 0 的索引
    • 如果对于串 A 和串 B ,前 i 个索引均一一对应相同,第 i+1 个索引满足 indexA[i] != indexB[i]
      • 如果 indexA[i] > indexB[i] ,则 A 串为 0 的这个索引更靠后,则 A 串排序后更靠前
      • 如果 indexA[i] < indexB[i] ,则 B 串为 0 的这个索引更靠后,则 B 串排序后更靠前
      • 如果 indexA[i] = indexB[i] ,则继续比较之后的索引,如果 A 和 B 所有为 0 的索引均相同,则比较 A 和 B 的编号,即第四关键字
  • 第四关键字是每个字符串的编号,从小到大

需要预处理出前两个关键字,第三关键字的比较需要至多 O ( m ) O(m) O(m) 次,最终都相同则按编号从小到大即可。

时间复杂度: O ( n m log ⁡ n ) O(nm\log n) O(nmlogn)

代码

n, m = map(int, input().split())
lst = input().split()

one = [0] * n
con = [0] * n
zero = [[] for _ in range(n)]

for i in range(n):
    s = lst[i]
    for j in range(m):
        if s[j] == '1':
            one[i] += 1
        else:
            zero[i].append(j)

    j = 0
    while j < m:
        if s[j] == '0':
            j += 1
            continue
        k = j + 1
        while k < m and s[k] == '1':
            k += 1
        con[i] = max(con[i], k - j)
        j = k

a = list(range(n))
a.sort(key=lambda x: (-one[x], -con[x], [-z for z in zero[x]], x))

print(*[x + 1 for x in a])
  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值