看到这个数据范围,我的第一想法是找找规律,看看最后的排列和n有没有什么关系。
果不其然,有规律:
奇数位置loc的值就是 (loc+1)/2。
偶数呢??如果忽略奇数位置的值,只看偶数位置的排列。
如果n为奇数(1、3除外):
例如:n=5,只看偶数位置的排列: 5 4
n=7 ,只看偶数位置的排列: 6 5 7
n=9,只看偶数位置的排列: 9 6 8 7
n=11,只看偶数位置的排列: 9 7 11 8 10
所以,从最小的位置开始,不断的跳 2^k (k最开始的值为1) ,就是下一个刚好比当前位置大1的数的位置。然后打了一个大一些的表,发现好像是每走到结尾一次,就k++。噢,那我就直接从小到大枚举k,再搞搞不就ac了。然后我就觉得可以美滋滋的过了,然后我样例都过不了┗( T﹏T )┛。
因为和正解没太多关系,就不继续扯了。n为偶数的时候,只是最小值的位置在第一个,最小值也有点不一样。有和上面是类似的规律。
看了一下别人的题解:他们都说直接 不断的把 x+=n-x/2就是了。直到x为奇数。有些人基本都没有解释。。。。。。
分析一下,对于每次查询的位置 x,如果我们能知道它原来的位置,不就知道它对应的值了么。
那对于查询的位置,我们就试试怎么把它还原回去吧。最开始,每个数字都是在奇数位置,最后部分的数变到了偶数位置。可以知道,如果还原到奇数位置,那就是它最开始的位置。
例如 n=6。那么最后的排列就是:1 4 2 6 3 5
那么对于4,它的位置是2。还原,就是把4放到现在的5 的后面。
就变成了1 _ 2 6 3 5 4。现在位置是7,是奇数位置,就代表它最初的位置就是7。
例子太简单了,再看看6这个数字。
1 4 2 6 3 5。它当前位置x是4。
它如果要还原到下一个位置,就要在它前面的偶数位置的数 全部都已经 还原到它后面的位置后 才能开始还原
——也就是4这个数移动到6之后,6再开始向后还原。
即 6前面有 x/2-1个偶数位。所以等x/2-1个数字放到它后面以后。它再还原。
最初它后面的数字个数就为 n-x,然后 前x/2-1个数字放到它后面。所以就有 n-x +(x/2-1) 即 n-x/2-1个数在它后面。
那么它就要+ n-x/2才能放到这n-x/2-1个数之后。
最后,代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long int n,x,q;
cin>>n>>q;
while(q--)
{
long long int loc;
cin>>loc;
while(loc%2==0)
{
loc=loc+n-loc/2;
}
cout<<loc/2+1<<endl;
}
return 0;
}