Codeforces——949B. A Leapfrog in the Array.

949B

看到这个数据范围,我的第一想法是找找规律,看看最后的排列和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
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<

 

 

你可能感兴趣的:(Codeforces——949B. A Leapfrog in the Array.)