POJ 2886 Who Gets the Most Candies? 线段树。。还有方向感

这道题不仅仅是在考察线段树,还他妹的在考察一个人的方向感。。。。

和线段树有关的那几个函数写了一遍就对了,连改都没改,一直在转圈的问题的出错。。。。

题意:从第K个同学开始,若K的数字为正 则往右转,否则往左转,转到的那同学出圈,知道剩下最后一个人。

   输出得到蛋糕最多的人的名字和块数。

线段树的节点中存的是这一段内还有几个人没有跳出,思路很简单,详见注释。

 

#include <iostream>

#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <queue>

#include <cmath>

#include <algorithm>



using namespace std;



int ncd[500010];



struct N

{

    int c;

    char n[11];

}pla[500010];



struct T

{

    int l,r,sur;

}st[2000010];



void init(int l,int r,int site)//初始化线段树

{

    st[site].l = l;

    st[site].r = r;

    st[site].sur = r-l+1;//开始时没有人跳出

    if(l == r)

        return ;

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



    init(l,mid,site<<1);

    init(mid+1,r,site<<1|1);

}



int F,Max;



int updata(int m,int site,int R)

{

    if(st[site].l == st[site].r)//此时已经找到了具体的人

    {

        st[site].sur--;//此段中有一人跳出



        if(Max < ncd[R])    //比较得到蛋糕书的多少

        {

            F = st[site].l;

            Max = ncd[R];

        }

        return pla[st[site].l].c;//返回卡片上的值

    }



    int ln = site<<1,rn = site<<1|1;

    //如果前半的段的人数 >= m 说明要找的人就在前半段

    //反之 就在后半段

    st[site].sur--;//此段中有一人跳出



    if(m <= st[ln].sur)

    {

        updata(m,ln,R);

    }

    else

    {

        updata(m-st[ln].sur,rn,R);

    }

}



int main()

{

    int i,j,k,n = sqrt(500000),m = 500000;

    int tempr;

    int tempc;



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

    {

        for(j = i;j <= m; ++j)

        {

            k = i*j;

            if(k <= 500000)

            {

                if(i == j)

                    ncd[k]++;

                else

                    ncd[k] += 2;

            }

            else break;

        }

    }



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

    {

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

        {

            scanf("%*c%s%d",pla[i].n,&pla[i].c);

        }



        init(1,n,1);



        tempr = k;



        //tempr为第i个要被删除的人在删除i-1个人之后的位置

        //tempc为第i个的人的卡片上的值

        

        F = k;

        Max = 1;

        for(i = 1;; ++i)

        {

            tempc = updata(tempr,1,i);

            if(i == n)

                break;



            m = n-i;//m为剩下的人数

            

            

            

            //下面讨论下一个要跳出的是谁。。。。错了N次。。。。

            if(tempc > 0)//往右转

            {

                tempc %= m;

                if(tempc == 0)//取余为零说明 tempc 为 m 的 倍数

                    tempc = m;

                if(tempc <= m-tempr+1)//m-tempr+1 为tempr之后的人数

                {

                    tempr += tempc - 1;

                }

                else

                {

                    tempr = tempc - m+tempr-1;

                }

            }

            else//往左转

            {

                tempc = - tempc;

                tempc %= m;

                if(tempc == 0)

                    tempc = m;

                if(tempc <= tempr-1)

                {

                    tempr = tempr-tempc;

                }

                else

                {

                    tempr += m-tempc;

                }

            }

        }

        printf("%s %d\n",pla[F].n,Max);

    }

    return 0;

}

 

 

 

你可能感兴趣的:(get)