问题描述
给定一个n长的数列,有m次操作,第i次操作表示将整个数列循环移动mi位,询问每次操作结束后的开头k个数字
输入格式
第一行三个整数n,m,k。
第二行n个整数表示数列。
接下来m行,每行一个整数mi,表示移动位数,若mi为正,表示向左移mi位,若mi为负数,表示向右移-mi位。
输出格式
m行,每行k个数,表示开头k个数字
样例输入
5 2 3
1 2 3 4 5
2
-2
样例输出
3 4 5
1 2 3
数据规模和约定
n<=1000000
m<=100000
k<=min(10,n)
mi<=100000000
首先说明一下这个题目的测试数据是有一点问题的
废话不多说,上思路:
第一次尝试
当我第一眼看到这个题目的时候,首先想到的就是列表的操作,如果m>0那么就将列表的每一个元素取出,添加到列表的末尾,同理,m<0 时就反过来嘛,最暴力的解法
n, m, k = map(int, input().split())
lst = list(map(int, input().split()))
m_value = [] # 记录所有的m
for i in range(m):
m_value.append(int(input()))
for i in m_value:
for j in range(abs(i)): # 对列表元素逐个移动
if i >= 0:
lst.append(lst.pop(0)) # 每次将列表第一个元素移到最后
else:
lst.insert(0, lst.pop(-1)) # 将列表末尾的元素移到最前面
print(' '.join(map(str, lst[:k])))
然后就……
果不其然的运行超时哈,然后我就想有没有什么办法可以批量移动列表,哎!还真有,那就是切片
第二次尝试
n, m, k = map(int, input().split())
lst = list(map(int, input().split()))
m_value = [] # # 记录所有的m
for i in range(m):
m_value.append(int(input()) % n)
for i in m_value:
lst = lst[i:] + lst[:i] # 列表的加法,这里i的值的正负均可用这个表达式表示
print(' '.join(map(str, lst[:k])))
然后又……
原来单个移动和批量移动本质上没什么区别啊……
第三次测试
后来我就想,既然输出的结果是一个列表的一小段连续的元素,既然移动列表就超时,那有没有什么办法可以不移动列表就达到需要的效果呢? 有!那就是标记每次移动后的起始位置,再取到后面的k个元素
n, m, k = map(int, input().split())
lst = list(map(int, input().split()))
m_value = [] # 记录所有的m
current_position = 0 # 记录每次索引移动后的起始位置
for i in range(m):
m_value.append(int(input()))
for i in m_value:
current_position += i
if current_position < 0: # 这两行if是控制索引的循环,使其不超过数的总数
current_position += n
if current_position > n:
current_position -= n
if current_position + k < n: # 当索引+k后不超过n
print(' '.join(map(str, lst[current_position:current_position + k])))
else: # 索引超过n后后面就要考虑从头开始了
print(' '.join(map(str, lst[current_position:n] + lst[0:k - (n - current_position)])))
然后结果就是……
哈哈哈哈,还是40分,但是和前面的区别就是:没有超时。然后我尝试将测试数据放在控制台进行测试,但遗憾的是测试台放不下这么多数据……大概是测试数据本身的问题吧……我是这样想的