2015年区域计算奥林匹克竞赛,2014年11月29日问题

时间:2019-03-12 09:41:23

标签: python python-3.x

需要有关此问题的帮助。 This is the problem

  

我们说,如果| x,则两个整数x和y的差值至少为K。   -y | ≥K(其差的绝对值至少为K)。给定   N个整数a1,a2,...,aN和K的序列,总变化计数   是序列中元素对的数量,其变化为   最小K,即它是对对的大小

{(i,j)|1≤i<j≤N and|ai−aj|≥K}
     

例如,如果K = 1且序列为3,2,4,则答案为3。如果K =   1,顺序为3、1、3,则答案为2。

     

您的任务是编写一个程序,该程序采用序列和值K   作为输入并计算总变异数。

     

输入格式

     

第一行包含两个正整数N和K,中间用a分隔   空间。

     

其后是包含N个由空格分隔的整数的行   给出序列的值。

     

输出格式

     

单行中的单个整数给出了总变化计数。

     

测试数据

     

您可以假设输入中的所有整数都在0到   10 ^ 8(含)。

Subtask 1 (40 marks) : 1 ≤ N ≤ 4000, 1 ≤ K ≤ 10^8

Subtask 2 (60 marks) : 1 ≤ N ≤ 65000, 1 ≤ K ≤ 10^8

我为此使用了O(n)解决方案,但仍然无法通过高级测试用例。您能否指出一些测试用例的执行时间很长,更重要的是如何解决这个问题。

n,k=map(int,input().split())
li=list(map(int,input().split()))
count=0
li.sort()
i=0
j=1
while(i<n and j<n):
    if(abs(li[i]-li[j])>=k):
        count+=(n-j)
        i+=1
        j=i+1
    else:
        j+=1
print(count)

1 个答案:

答案 0 :(得分:0)

您的解决方案肯定是 O(n),因为您使用的是list.sort(),时间复杂度为O(n log n)(它使用的是Timsort内部)。


据我所知,您的方法似乎合理。只是一些改进提示:

  • 使用临时变量(elem_i)来保存num_list[i],因此您不需要进行如此多的列表查找。
  • 由于对列表进行了排序,因此可以通过重新排列两个变量来忽略对abs()的调用(元素j始终大于或等于i)。

这是您的(f1())和我的(f2())版本的代码;它被编写为函数,因此我可以对其进行基准测试:

def f1(num_list, k):
    num_list.sort()
    n = len(num_list)

    count = 0
    i = 0
    j = 1
    while i < n and j < n:
        if abs(num_list[i] - num_list[j]) >= k:
            count += (n-j)
            i += 1
            j = i + 1
        else:
            j += 1

    return count

def f2(num_list, k):
    num_list.sort()
    n = len(num_list)

    count = 0
    i = 0
    j = i + 1
    elem_i = num_list[i]

    while i < n and j < n:
        if num_list[j] - elem_i >= k:
            count += (n - j)
            i += 1
            j = i + 1
            elem_i = num_list[i]
        else:
            j += 1

    return count

以我的代码为基准:

import timeit
import random

for n in [1000, 4000, 10000]:
    numbers = [random.randint(0, 10**8) for _ in range(n)]

    for k in [10**1, 10**3, 10**5, 10**7]:
        t1 = timeit.timeit(
            'f(numbers, k)', 'from __main__ import numbers, k, f1 as f',
            number=10)
        t2 = timeit.timeit(
            'f(numbers, k)', 'from __main__ import numbers, k, f2 as f',
            number=10)

        print('n {:10,d} | k {:10,d} | {:10.4f} | {:10.4f} | best f{}'.format(
            n, k, t1, t2, '1' if t1 < t2 else '2'))
        assert f1(numbers, k) == f2(numbers, k)

这些结果给了我

n      1,000 | k         10 |     0.0026 |     0.0020 | best f2
n      1,000 | k      1,000 |     0.0026 |     0.0020 | best f2
n      1,000 | k    100,000 |     0.0044 |     0.0033 | best f2
n      1,000 | k 10,000,000 |     0.1585 |     0.0919 | best f2
n      4,000 | k         10 |     0.0102 |     0.0074 | best f2
n      4,000 | k      1,000 |     0.0097 |     0.0076 | best f2
n      4,000 | k    100,000 |     0.0365 |     0.0243 | best f2
n      4,000 | k 10,000,000 |     2.3722 |     1.3992 | best f2
n     10,000 | k         10 |     0.0255 |     0.0190 | best f2
n     10,000 | k      1,000 |     0.0260 |     0.0194 | best f2
n     10,000 | k    100,000 |     0.1938 |     0.1190 | best f2
n     10,000 | k 10,000,000 |    15.2469 |     9.0770 | best f2

这不是很大的进步,但这是有的。不过,我不知道它是否对您有帮助。