J Josephus Transform(x次連續的k-約瑟夫變換,利用線段樹找位置)
阿新 • • 發佈:2020-08-05
題: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];View Codevoid 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; }