天天看点

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