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

题目链接 https://cn.vjudge.net/problem/POJ-2886

【题意】
N N 个孩子顺时针坐成一个圆圈(编号从 1 1 N N ),每个孩子手中有一张卡片(上有一个非0整数)现在让第K个孩子先淘汰,如果该孩子手中卡片上的数字A大于零,下一个出圈的是他左手边第A个孩子,否则,下一个出圈的是他右手边第A个孩子(当前孩子已经不算在圈中了)
p p 个出圈的孩子会得到 F ( p ) F(p) 个糖果, F ( p ) F(p) p p 的约数个数。输出得到糖果数最多的孩子名字和得到的糖果数。

【思路】
首先预处理所有数的约数个数,存入数组中.
假设当前出圈的是剩余孩子中的第 K K 个(下标1开始),他手中的数字为 A A 那么
A > 0 A>0 下次被淘汰的是剩余孩子中的第 ( ( K 2 + A ) % m o d + m o d ) % m o d + 1 ((K-2+A)\%mod+mod)\%mod+1
A < 0 A<0 下次被淘汰的是剩余孩子中的第 ( ( K 1 + A ) % m o d + m o d ) % m o d + 1 ((K-1+A)\%mod+mod)\%mod+1
上面的公式是先变成从0下标开始便于取模,最后取完模再+1. 其中 m o d mod 是当前剩余的人数,每次都会-1,用线段树模拟

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]
using namespace std;

const int maxn=500005;

struct Tree{
	int left,right;
	int sum;
}tree[maxn<<2];

int n,k;
char s[maxn][15];
int a[maxn];
int fac[maxn];

void pushup(int id){ node.sum=lson.sum+rson.sum; }

void build(int id,int le,int ri){
	node.left=le;
	node.right=ri;
	node.sum=ri-le+1;
	if(le==ri) return;
	int mid=(le+ri)>>1;
	build(id<<1,le,mid);
	build(id<<1|1,mid+1,ri);
}

int query(int id,int val){
	if(node.left==node.right) return node.left;
	if(lson.sum>=val) return query(id<<1,val);
	else return query(id<<1|1,val-lson.sum);
}

void update(int id,int pos){
	if(node.left==node.right){
		node.sum=0;
		return;
	}
	int mid=(node.left+node.right)>>1;
	if(pos<=mid) update(id<<1,pos);
	else update(id<<1|1,pos);
	pushup(id);
}

void init(){
	for(int i=1;i<maxn;++i){
		for(int j=i;j<maxn;j+=i){
			++fac[j];
		}
	}
}

int main(){
	//freopen("in.txt","r",stdin);
	init();
	while(scanf("%d%d",&n,&k)==2){
		for(int i=1;i<=n;++i) scanf("%s%d",s[i],&a[i]);
		build(1,1,n);
		int ans=-1,id=-1;
		for(int cnt=1;cnt<=n;++cnt){
			int pos=query(1,k);
			//cout<<pos<<endl;
			if(fac[cnt]>ans){
				ans=fac[cnt];
				id=pos;
			}
			if(cnt==n) break;
			update(1,pos);
			int mod=n-cnt;
			if(a[pos]>0){
				k=((k-2+a[pos])%mod+mod)%mod+1;
			}
			else if(a[pos]<0){
				k=((k-1+a[pos])%mod+mod)%mod+1;
			}
		}
		printf("%s %d\n",s[id],ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_k666/article/details/82845140