算导上有这样一道题,假设n个人站成环形,且有一个正整数m<=n。从某个指定的人开始,沿环报数,每遇到第m个人就让其出列,且报数继续进行下去。执行这一过程,直到所有人出列。每个人出列的次序定义为整数1,2,3,…,n的(n,m)-Josephus排列。
例如,(7,3)-Josephus排列为(3,6,2,7,5,1,4)。
设计一个算法,时间复杂度要求O(nlogn)时间,使给定的整数n和m,输出(n,m)-Josephus排列。
对于约瑟夫环问题,如果是求最后一个出列的人,有O(n)的算法,这里就不介绍。
这里如果我们用循环队列来模拟的话,很明显时间复杂度是O(nm)的,而且代码比较难写。既然算导说有O(nlogn)的算法那就肯定有啦,答案是线段树。
下面我们画出线段树:
调用build(1,n,1)函数建树
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[N<<2];
int tree[N<