Codeforces Round #469 (Div. 2) D. A Leapfrog in the Array (思维)

这里写图片描述

题目大意:最开始n个数字中的数字i在位置2*i-1,之后从右向左依次用数字将该列填充。最后q个query问你pos为Xi该填上什么数字。

解析:首先n范围1e18,直接模拟肯定不行,但肯定有什么规律在里面,我们自己写写看n=6的时候,1~6位置分别为1 4 2 6 3 5,n=3的时候1~3位置分别为1 3 2,这里我们可以明显的发现,当Xi&1时,该位置最后的数字就是Xi/2+1。

证明以上的小小推论也很简单,因为最初有2*n个位置,实际上只有n个数字,那么在最左边n个位置中的奇数位置的数字其实不可能发生移动。

之后我们考虑其他位置,我们一个数字(在位置pos)一次跳跃的前提是他相邻的左边有任意个连续的填充块,
这左边所有的填充块中其中有pos/2个数字在最初就在他的左边,剩下还有n-pos/2-1个数字最初在他的右边,因此我们可以推出,如果逆推回去,设query中的位置为p,那么每一次跳跃后的位置就是p+(n-p/2-1)+1,当(p+(n-p/2))&1时说明他到了最初的位置,这时候(New Xi)/2+1即为answer

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
using namespace std;
typedef long long ll;

#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define pi acos(-1.0)
#define lson  root << 1
#define rson  root << 1 | 1

ll n,q;

ll a[200005];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>q;
    for(int i=0;i<q;i++)
    {
        ll x;
        cin>>x;
        while(1)
        {
            if(x%2==1)
                break;
            x=x+(n-x/2);
        }
        cout<<x/2+1<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/murphyc/article/details/79505485