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