天天看點

1009: Josephus環的複仇1009: Josephus環的複仇

1009: Josephus環的複仇

時間限制: 1 Sec  記憶體限制: 128 MB

送出: 170  解決: 15

[送出][狀态][讨論版]

題目描述

任給正整數n、k,按下述方法可得排列1,2,……,n的一個置換:将數字1,2,.. .,n環形排列,按順時針方向從1開始計數;計滿K時輸出該為之上的數字(并從環中删去該數字),然後從下一個數字開始繼續計數,直到環中所有數字均被輸出為止。試編寫一算法,對輸人的任意正整數n、k(n>=k>0),輸出相應的置換。

資料結構老師沒有告訴xry111這題n、k的上限,是以xry111自作主張地認為n<=200000。請解決這一問題。

輸入

單組資料,包含2個整數n、k(0<k<=n<=200000)。

輸出

輸出1行,包含n個整數(含義如題目描述),用空格分割。

行末不要有多餘的空格。

樣例輸入

10 3      

樣例輸出

3 6 9 2 7 1 8 5 10 4

      
#include<bits/stdc++.h> 
#define REP(i,a,b) for(int i=a;i<=b;i++) 
#define MS0(a) memset(a,0,sizeof(a)) 
#define lson l,m,rt<<1 
#define rson m+1,r,rt<<1|1 
  
using namespace std; 
  
typedef long long ll; 
const int maxn=200100; 
const int INF=(1<<29); 
  
int n,k,K; 
struct SegTree 
{ 
    int l,r; 
    int id,cnt; 
    void debug() 
    { 
        printf("%2d %2d %2d %2d\n",l,r,id,cnt); 
    } 
};SegTree T[maxn<<2]; 
  
void push_up(int rt) 
{ 
    T[rt].cnt=T[rt<<1].cnt+T[rt<<1|1].cnt; 
} 
  
void build(int l,int r,int rt) 
{ 
    T[rt].l=l;T[rt].r=r; 
    if(l==r){ 
        T[rt].id=l; 
        T[rt].cnt=1; 
        return; 
    } 
    int m=(l+r)>>1; 
    build(lson); 
    build(rson); 
    push_up(rt); 
} 
  
int query(int L,int R,int l,int r,int rt) 
{ 
    if(L<=l&&r<=R) return T[rt].cnt; 
    int m=(l+r)>>1; 
    int res=0; 
    if(L<=m) res+=query(L,R,lson); 
    if(R>m) res+=query(L,R,rson); 
    return res; 
} 
  
void update(int p,int c,int l,int r,int rt) 
{ 
    if(l==r){ 
        T[rt].cnt=c; 
        return; 
    } 
    int m=(l+r)>>1; 
    if(p<=m) update(p,c,lson); 
    else update(p,c,rson); 
    push_up(rt); 
} 
  
int bin(int p,int l,int r) 
{ 
    while(l<r){ 
        int m=(l+r)>>1; 
        int ls=query(l,m,1,n,1); 
        if(p<=ls) r=m; 
        else l=m+1,p-=ls; 
    } 
    return l; 
} 
  
int main() 
{ 
    while(~scanf("%d%d",&n,&k)){ 
        build(1,n,1); 
        int cur=1; 
        REP(i,1,n){ 
            cur=(cur+k-1)%T[1].cnt; 
            if(cur==0) cur=T[1].cnt; 
            int p=bin(cur,1,n); 
            if(i==n) printf("%d\n",p); 
            else printf("%d ",p); 
            update(p,0,1,n,1); 
        } 
    } 
    return 0; 
} 
  
/************************************************************** 
    Problem: 1009 
    User: 14030140102 
    Language: C++ 
    Result: 正确 
    Time:716 ms 
    Memory:14196 kb 
****************************************************************/       

View Code

#include<bits/stdc++.h> 
#define REP(i,a,b) for(int i=a;i<=b;i++) 
#define MS0(a) memset(a,0,sizeof(a)) 
#define lson l,m,rt<<1 
#define rson m+1,r,rt<<1|1 
  
using namespace std; 
  
typedef long long ll; 
const int maxn=200100; 
const int INF=(1<<29); 
  
int n,k; 
int c[maxn];

int lowbit(int x)
{
    return x&(-x);
}

void add(int p,int x)
{
    while(p<=n){
        c[p]+=x;
        p+=lowbit(p);
    }
}

int sum(int p)
{
    int res=0;
    while(p>0){
        res+=c[p];
        p-=lowbit(p);
    }
    return res;
}
  
int bin(int p,int l,int r) 
{ 
    while(l<r){ 
        int m=(l+r)>>1; 
        int ls=sum(m)-sum(l-1);
        if(p<=ls) r=m; 
        else l=m+1,p-=ls; 
    } 
    return l; 
} 
  
int main() 
{ 
    while(~scanf("%d%d",&n,&k)){ 
        MS0(c);
        int cur=1; 
        REP(i,1,n) add(i,1);
        REP(i,1,n){ 
            int cnt=sum(n);
            cur=(cur+k-1)%cnt; 
            if(cur==0) cur=cnt; 
            int p=bin(cur,1,n); 
            if(i==n) printf("%d\n",p); 
            else printf("%d ",p);
            int x=sum(p)-sum(p-1);
            add(p,-x); 
        } 
    } 
    return 0; 
}      

View Code

轉載于:https://www.cnblogs.com/--560/p/4947308.html