Who Gets the Most Candies? POJ - 2886(线段树)


题意:一群小孩围坐成一圈,按顺时针方向编号为1~N;每个孩子手里拿着一张纸片,上边有一个非零整数x;
从第k个孩子开始淘汰,当某一孩子淘汰后,下一个淘汰的和他手上的纸片有关:
纸片上的数x大于0,淘汰他左边的第x个孩子,反之淘汰他右边的第x个孩子;
第i个淘汰的孩子会得到i的约数的个数块糖,即:若是第4个淘汰,4有1,2,4三个约数,那么就得到3块糖;

思路:
首先要知道第几个淘汰的分到的糖多,即:1~N那个数的约数多; 
直接求每个数的约数,这里有个优化:
对每个数都求一遍约数显然复杂度太高,我们反过来想,看每个数是谁的约数;

最后就是要模拟这个特殊的约瑟夫环了;假设已经找到1~N约数最多的是P,怎样快速找到第P个淘汰的人呢?

我的想法是用线段树,其叶子就表示孩子1~N编号,只要能找到每次淘汰的是剩下的人中第几个就可以了;

假设共有4人,当前被淘汰的是第2个,手中的数字是3,那么下一个被淘汰的是剩下人中的第几个呢?

如上图去掉2后,左手边第3个是1,是剩下的人中第1个;

...

经过观察得:当x>0时,k=((k-1+x-1)%mod+mod)%mod+1;

                        当x<=0时,k=((k-1+x)%mod+mod)%mod+1;

其中k表示上一个被淘汰的是第几个,mod表示当前剩余人数;

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 500100;
int id, n, k;
int ans[maxn];
struct node{
	int A;
	char name[15];
}pers[maxn];
void init(){
	memset(ans, 0, sizeof(ans));
	for(int i=1; i<=n; i++){
		ans[i]++;
		for(int j=i+i; j<=n; j+=i){
			ans[j]++;
		}
	}
	id=1;
	int m=ans[1];
	for(int i=1; i<=n; i++){
		if(m<ans[i]){
			id=i;
			m=ans[i];
		}
	}
}
struct Node{
	int x, l, r;
}tree[maxn<<2];
void updown(int m){
	tree[m].x=tree[m<<1].x+tree[m<<1|1].x;
	return;
}
void build(int m, int l, int r){
	tree[m].l=l;
	tree[m].r=r;
	if(l==r){
		tree[m].x=1;
		return;
	}
	int mid=(l+r)>>1;
	build(m<<1, l, mid);
	build(m<<1|1, mid+1, r);
	updown(m);
}
int updata(int m, int v){
	if(tree[m].r==tree[m].l){
		tree[m].x=0;
		return tree[m].l;
	}
	int temp;
	if(tree[m<<1].x>=v) temp=updata(m<<1, v);
	else temp=updata(m<<1|1, v-tree[m<<1].x);
	updown(m);
	return temp;
}
int main(){
	while(~scanf("%d%d", &n, &k)){
		for(int i=1; i<=n; i++){
			scanf("%s%d", pers[i].name, &pers[i].A);
		}
		init();
		build(1, 1, n);
		int t=id;
		pers[0].A=0;
		int pos=0;
		int mod=n;
		while(t--){
			if(pers[pos].A>0){
				k=((k-1+pers[pos].A-1)%mod+mod)%mod+1;
			}
			else{
				k=((k-1+pers[pos].A)%mod+mod)%mod+1;
			}
			pos=updata(1, k);
			mod=tree[1].x;
		}
		printf("%s %d\n", pers[pos].name, ans[id]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sirius_han/article/details/81002479
今日推荐