1 2 3 4

Josephus Transform 加速置换

https://ac.nowcoder.com/acm/contest/5671/J

牛客多校j题,利用线段树nlogn写出模拟的操作快速幂

可以类似给转圈用

#include<iostream>
#include<set>
using namespace std;
typedef long long ll;
const int maxn = 2e5+11;
int list[maxn];
int vis[maxn];
int a[maxn];

set<int>ins;
set<int>::iterator it;
int n,m;
/*
cnt--;
p = (p%cnt + k - 1)%cnt;
*/

int tree[maxn*4];
int update(int node,int be,int en,int i,int val) {
	int l = node*2;
	int r = node*2+1;
	int mid = be+en>>1;
	if(be == en) {
		tree[node] = val;
		return 0;
	}

	if(i <= mid) update(l,be,mid,i,val);
	else update(r,mid+1,en,i,val);
	tree[node] = tree[l] + tree[r];
	return 0;
}
int ans;


int qurry(int node,int be,int en,int sum) {
	int l = node*2;
	int r = node*2+1;
	int mid = be+en>>1;
	if(be == en) {
		tree[node] --;
		ans = be;
		return 0;
	}
	if(sum <= tree[l]) {
		qurry(l,be,mid,sum);
	} else {
		qurry(r,mid+1,en,sum - tree[l]);
	}
	tree[node] = tree[l] + tree[r];
	return 0;
}

int cal(int *list,int *a) { //按照a的规则跑
	for(int i=1; i<=n; i++) {
		vis[i] = list[a[i]];
	}
	for(int i=1; i<=n; i++) {
		list[i] = vis[i];
	}
	return 0;
}

int main() {
	scanf("%d %d",&n,&m);
	for(int i=1; i<=n; i++) {
		list[i] = i;
		update(1,1,n,i,1);
	}


	while(m--) {
		int k,x;
		scanf("%d %d",&k,&x);
		int p = k-1;
		int cnt = n;
		for(int i=1; i<n; i++) {
			qurry(1,1,n,p+1);
			a[i] = ans;
			cnt--;
			p = (p%cnt + k - 1)%cnt;
		}
		qurry(1,1,n,p+1);
		a[n] = ans;
		for(int i=1;i<=n;i++){
			update(1,1,n,i,1);
		}
		
		while(x){
        	if(x&1){
        		cal(list,a);
			}
			x>>=1;
			cal(a,a);
		}
	}

	for(int i=1; i<=n; i++) {
		printf("%d ",list[i]);
	}
	printf("\n");
	return 0;
}

  

                                                 

posted @ 2020-09-07 19:43  Lesning  阅读(126)  评论(0编辑  收藏  举报