您的位置:首页 > 其它

POJ 2886 Who Gets the Most Candies?

2014-09-22 17:32 323 查看
题目:http://poj.org/problem?id=2886

题意:

有一个n个人围成圆圈,每次有一个人出圈,下一次出圈的人由本次出圈的人决定。

按照出圈的顺序,每个人可以获得不同的糖果,找出可以获得最多糖果的人。

 第p个出圈的人可以获得F(p)个糖果。 

思路:

用线段树维护剩余的人数。

约瑟夫环+线段树+反素数

#include <iostream>
#include <cstdio>

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;
const int maxn = 500005;
int tree[maxn << 2];
struct child{
char name[20];
int card;
}cc[maxn];

void PushUp(int rt){
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}

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

void update(int p, int l, int r, int rt){
if (l == r) {
tree[rt] = 0; return;
}
int m = (l + r) >> 1;
if (m >= p) update(p,lson);
else update(p, rson);
PushUp(rt);
}

int query(int k, int l, int r, int rt){
if (l == r)
return l;
int m = (l + r) >> 1;
if (tree[rt << 1] >= k)
return query(k, lson);
else
return query(k - tree[rt << 1], rson);
}
int hash[maxn];
void init(){//打出反素数表
for (int i = 1; i <= maxn; i ++){
hash[i] ++;
for (int j = 2*i; j <= maxn; j += i)
hash[j] ++;
}
}
int main(){
init();
int n, k;
while (scanf ("%d %d", &n, &k) != EOF){

for(int i = 1;i <= n;i++)
scanf("%s%d",cc[i].name,&cc[i].card);

build (1, n, 1);

int maxtemp = hash[1];
int kk = 1;
for(int i = 2;i <= n;i++){
if(maxtemp<hash[i]){
maxtemp = hash[i];
kk = i;
}
}
int pos = k; //k为人在约瑟夫环中的相对位置,pos为该人在最初的环中的绝对位置
for(int i = 1;i < kk;i++) {
update (pos, 1, n, 1); //删除当前这个人
//求出下一个人的在约瑟夫环中的相对位置
k += cc[pos].card;
if (cc[pos].card > 0) k--; //注意:当num[pos]>0时,pos后面的人的相对位置都要减1
k = (k % tree[1] + tree[1]) % tree[1]; //sum[1]为剩余人的人数
if (k == 0) k = tree[1];
//由相对位置求出绝对位置
pos = query(k, 1, n, 1);
}
printf ("%s %d\n", cc[pos].name,hash[kk]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: