poj 2886 Who Gets the Most Candies

http://poj.org/problem?id=2886

这个题和插队买票那题一样 http://www.cnblogs.com/liulangye/archive/2012/06/11/2545529.html

题目大意:

一些人围成一圈第一个人跳出圈后会告诉你下一个谁跳出来

跳出了的人所得到的糖果数量和他跳出的顺序有关

线段树在这里只是一个二分搜索的作用

思路:

1.求第几个跳出者所得糖果数量

2.根据输入范围,求的第几个人是得到糖果最多的 假设是J

3.建立线段树,线段树区间表示区间内人的个数,

搜索第几个人时所经过的路径区间人数的减一

然后根据提示求的下一个跳出的人是谁  并记录第J个人是谁

代码及其注释:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<cmath>

#include<queue>

#include<algorithm>

#include<vector>

using namespace std;

const int N=500005;

struct node

{

    int l,r;

    int sum;

}mem[N*3];

struct node1

{

    char name[12];

    int a;

}step[N];//输入名字 及其下一个跳出提示

int candysum[N];//第i个人跳出所得糖果

int ansi;//得糖果最多的人的输入序号

int I,n,c,J;//J表示第几个跳出的人得到的糖果最多

void ready()//求第i人跳出最得到的糖果数量

{

    memset(candysum,0,sizeof(candysum));

    for(int i=1;i<N;++i)

    {

        ++candysum[i];

        for(int j=i*2;j<N;j=j+i)

        {

            ++candysum[j];

        }

    }

}

void build(int x,int l,int r)//建树

{

    mem[x].l=l;

    mem[x].r=r;

    mem[x].sum=(r-l+1);

    if(mem[x].l==mem[x].r)

    return;

    int mid=(r+l)>>1;

    build(x*2,l,mid);

    build(x*2+1,mid+1,r);

}

void jump(int x,int s)//s表示目前队列此区间第几个人跳出

{

    --mem[x].sum;//所到区间人数减一

    if(mem[x].l==mem[x].r)//最后结点

    {

        if(J==c)

        {

            ansi=mem[x].l;//如果是的J个人跳出 记录答案

        }

        if(n-c==0)//全跳出

        return ;

        if(step[mem[x].l].a>0)//以下是求出目前队列从线段树左起下一次第几个人跳出

        --I;

        I=((I+step[mem[x].l].a)%(n-c)+(n-c))%(n-c);

        if(I==0)

        I=n-c;

    }

    else

    {

        if(mem[x*2].sum>=s)//左边人数足够则向左搜

        {

            jump(x*2,s);

        }

        else

        {

            s-=mem[x*2].sum;//否则减去左边人数向右搜

            jump(x*2+1,s);

        }

    }

}

int main()

{

    int k;

    ready();

    while(scanf("%d %d",&n,&k)!=EOF)

    {

        J=1;

        for(int i=1;i<=n;++i)

        {

            getchar();

            scanf("%s %d",step[i].name,&step[i].a);

            if(candysum[i]>candysum[J])

            J=i;

        }

        build(1,1,n);

        I=k;

        for(c=1;c<=n;++c)

        {

            jump(1,I);

        }

        printf("%s %d\n",step[ansi].name,candysum[J]);

    }

    return 0;

}

  

 

 

 

你可能感兴趣的:(get)