POJ-2886___Who Gets the Most Candies?——线段树 + 反素数

题目链接:点我啊╭(╯^╰)╮

题目大意:

     有 nnn 个人,第一次选择第 kkk 个人退出,每个人都有一个整数值 kkk,整数代表向左数第k个人退出,负数则向右数
     每个人在退出时,会得到一定数量的糖果,若则个人是第 mmm 个退出的,则可以得到 mmm 的因数 个糖果,问得到最大糖果数量的那个孩子是谁??

解题思路:

    反素数问题,什么是反素数可以自行百度,问题就转化为了求最接近n的反素数,反素数可以暴力求出和或者打表,下面的代码给出了暴力的过程
    这题同时由于给出了顺序,所以这个退出的过程就必须模拟

    那么问题就在于怎么处理这个退出的过程了,要实现 log(n)log(n)log(n) 的时间,这里引入线段树的单点更新,本题和POJPOJPOJ 282828282828很相似,可以点进去看一下

代码思路:

    和POJPOJPOJ 282828282828一样处理好单点更新的过程,还有暴力打表的过程,对正负数的处理可以用模处理,看代码即可

核心:线段树的好题,同时了解到反素数的好处

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pushup(rt) t[rt] = t[rt<<1] + t[rt<<1|1];
const int maxn = 500000+10;
ll t[maxn<<2], a[maxn][5], ans[maxn], id, n;
struct Node {
	char name[20];
	int val;
} boy[maxn];

void build(int l,int r,int rt) {
	if(l==r) {
		t[rt] = 1;
		return ;
	}
	int m = (l+r)>>1;
	build(lson);
	build(rson);
	pushup(rt);
}

int update(int pos,int l,int r,int rt) {
	if(l==r) {
		t[rt]--;
		return l;
	}
	int m = (l+r)>>1, ret;
	if(pos<=t[rt<<1]) ret = update(pos,lson);
	else ret = update(pos-t[rt<<1],rson);
	pushup(rt);
	return ret;
}

void init() {
	memset(ans, 0, sizeof(ans));
	for(int i=1; i<=n; i++) {
		ans[i]++;
		for(int j=2*i; j<=n; j+=i)
			ans[j]++;
	}
	id = 1;
	int maxx = ans[1];
	for(int i=2; i<=n; i++) //找出第几个人跳出获得的糖最多
		if(ans[i]>maxx) {
			maxx=ans[i];
			id=i;
		}
}

void printf_ans(int l,int r,int rt){
	if(l==r){
		printf("%d ", t[l]);
		return ;
	}
	int m = (l+r)>>1;
	printf_ans(lson);
	printf_ans(rson);
}

int main() {
	int k;
	while(~scanf("%d%d", &n, &k)) {
		build(1,n,1);
		init();
		for(int i=1; i<=n; i++) scanf("%s %d", boy[i].name, &boy[i].val);
		int pos=0, mod=t[1];
        boy[0].val=0;
        int ans_id = id;
		while(id--) {
			if(boy[pos].val>0)  //k表剩余的人中从左起第k中出队
				k=((k-1+boy[pos].val-1) % mod+mod) % mod+1;
			else
				k=((k-1+boy[pos].val) % mod+mod) % mod+1;
				
			pos = update(k,1,n,1);
			mod=t[1];
		}
		printf("%s %d\n", boy[pos].name, ans[ans_id]);
	}
}
上一篇:关闭ES动态创建mapping


下一篇:菜鸟系列 Leetcode —— 1103. 分糖果 II