Who Gets the Most Candies? 线段树

用模拟每一轮有人跳出后的人数变化

因子个数可打表算出


#include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 500005;
typedef long long ll;
#define lson rt << 1, l, m
#define rson rt << 1 | 1, m + 1, r
struct Node {
	ll l, r, num;
	ll mid() { return (l + r) >> 1; }
} Tree[MAXN * 4];
char name[MAXN][15];
int card[MAXN];
int table[MAXN];

void init_divide()
{
	for (int i = 1; i <= MAXN; ++i)
	{
		++table[i];
		for (int j = 2 * i; j <= MAXN; j += i)
			++table[j];
	}
}
void buildTree(int rt, int l, int r)
{
	Tree[rt].l = l;
	Tree[rt].r = r;
	Tree[rt].num = r - l + 1;
	if (l == r)
		return;
	int m = Tree[rt].mid();
	buildTree(lson);
	buildTree(rson);
}

int query(int rt, int n)
{
	--Tree[rt].num;
	if (Tree[rt].l == Tree[rt].r)
		return Tree[rt].l;
	if (Tree[rt << 1].num >= n)
		return query(rt << 1, n);
	else
		return query(rt << 1 | 1, n - Tree[rt << 1].num);
}



int main(void)
{
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	/*ios::sync_with_stdio(false);
	cin.tie(0);*/
	init_divide();
	int n, k;
	while (scanf("%d %d", &n, &k) != EOF)
	{
		buildTree(1, 1, n);
		for (int i = 1; i <= n; ++i)
			scanf(" %s %d", name[i], &card[i]);

		int id = 1;
		for (int i = 2; i <= n; ++i)
			if (table[id] < table[i])
				id = i;

		int mod = Tree[1].num;
		int pos = 0;
		card[0] = 0;
		n = id;
		while (n--)
		{
			if (card[pos] > 0)
				k = ((k - 1 + card[pos] - 1) % mod + mod) % mod + 1;//因为下标是从1开始的,所以先减一,把下标调为从0开始,后再加1
			else
				k = ((k + card[pos] - 1) % mod + mod) % mod + 1;//card[i]<= 0则是逆时针,k不需要变为k-1
			pos = query(1, k);
			mod--;
		}
		printf("%s %d\n", name[pos], table[id]);
	}


	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值