J Josephus Transform(x次连续的k-约瑟夫变换,利用线段树找位置)

题:https://ac.nowcoder.com/acm/contest/5671/J

题意:初始序列为1 2 3。。。n,给定m个操作[k,x]代表对序列连续执行x次k-约瑟夫变换

题解:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int M = 1e5+5;
int tr[M<<2];
void up(int root){
    tr[root]=tr[root<<1]+tr[root<<1|1];
}
void build(int root,int l,int r){
    tr[root]=0;
    if(l==r){
        tr[root]=1;
        return ;
    }
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
    up(root);
}
void update(int pos,int root,int l,int r){
    if(l==r){
        tr[root]=0;
        return ;
    }
    int midd=(l+r)>>1;
    if(pos<=midd)
        update(pos,lson);
    else
        update(pos,rson);
    up(root);
}
int query(int num,int root,int l,int r){
    if(l==r)
        return l;
    int midd=(l+r)>>1;
    if(num<=tr[root<<1])
        return query(num,lson);
    else
        return query(num-tr[root<<1],rson);
}
///i位置要取到a[i]位置的值
int a[M],b[M],c[M],d[M],res[M];
int n,m;
int k,x;
void quick_pow(int y){
    for(int i = 1;i <= n;i++)res[i] = i;
    while(y){
        if(y&1){
            for(int i=1;i<=n;i++)d[i]=res[i];
            for(int i=1;i<=n;i++)res[i]=d[a[i]];
        }
        ///快速幂跳转1、2、4、8....次
        for(int i=1;i<=n;i++)c[i]=a[i],d[i]=a[i];
        for(int i=1;i<=n;i++)a[i]=c[d[i]];
        y >>= 1;
    }
    return;
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        b[i] = i;
    while(m--){
        build(1,1,n);
        cin>>k>>x;
        int pos=1;
        for(int i=1;i<=n;i++){
            pos =(pos-1+k-1)%(n-i+1)+1;
            a[i]=query(pos,1,1,n);
            update(a[i],1,1,n);
        }
        quick_pow(x);
        for(int i=1;i<=n;i++)c[i]=b[i];
        for(int i=1;i<=n;i++)b[i]=c[res[i]];
    }
    for(int i=1;i<=n;i++)cout<<b[i]<<" ";
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/13443130.html