XDOJ 1009: Josephus环的复仇

思路:通过样例找出规律,大概就是每次线段树维护后,能够确定找到下一个输出的位置,然后把这个位置的叶子节点设置为0,再次维护线段树即可;
#include<algorithm> 
#include<queue>
#include<iostream>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 200005
using namespace std;
int b[N];
typedef struct node{
	int x;int y;int date;
}node;
node a[N*4];
void built(int root,int first,int end){
	if(first==end){
		a[root].x=first;a[root].y=end;a[root].date=1;
		return ;
	}
	int mid=(first+end)/2;
	built(2*root,first,mid);
	built(2*root+1,mid+1,end);
	a[root].x=a[root*2].x;a[root].y=a[root*2+1].y;a[root].date=a[root*2].date+a[root*2+1].date;
}
void U(int root,int first,int end,int r){
	if(first==r&&end==r){
		a[root].date=0;
		return ;
	}
	int mid=(first+end)/2;
	if(r>mid)  U(root*2+1,mid+1,end,r);
	else  U(root*2,first,mid,r);
	a[root].date=a[root*2].date+a[root*2+1].date;
}
int sum;
void Q(int root,int first,int end,int e){
//	cout<<first<<"  "<<end<<endl;
	if(first==end){
		sum=a[root].y;
	//	cout<<sum<<endl;
		return ;
	}
	int mid=(first+end)/2;
	if(e<=a[root*2].date) Q(root*2,first,mid,e);
	else if(e>a[root*2].date)  Q(root*2+1,mid+1,end,e-a[root*2].date); 
}
int main(){
	int n,k;
	scanf("%d %d",&n,&k);
	for(int i=1;i<=n;i++){
		b[i]=i;
	}
	built(1,1,n);
	int p=k;
	for(int i=1;i<=n;i++){
		int aa=k%(n-i+1);
		if(aa==0)  aa=(n-i+1);
	//	cout<<aa<<endl;
		Q(1,1,n,aa);
	//	cout<<sum<<endl;
		if(i==1){
			printf("%d",b[sum]);
		}
		else{
			printf(" %d",b[sum]);
		}
		U(1,1,n,sum);
		aa+=(p-1);
		k=aa;
	}
	return 0;
}

posted @ 2017-10-03 20:25  wang9897  阅读(143)  评论(0编辑  收藏  举报