POJ 2886 Who Gets the Most Candies? 线段树

题意:几个人围成一个圈,第K个人开始出圈,k说出一个数(!=0)a,a>0表示左边的第a个人出列,a<0表示左边的d第a个人出列 ,直到最后一个人出圈

每个人出圈都有一个序号,如第一个出圈,第二个。。。找出所有序号中最大的反素数,反素数!!!找了一个表贴上了

这里讲的反素数 http://www.cnblogs.com/jackiesteed/articles/2018868.html

http://www.cnblogs.com/xiaoxian1369/archive/2011/08/05/2129031.html

(写的晕晕的,to me好不容易),其中找下一个位置的计算 假设位置是从 1~N,K为当前出圈的位置,该人说出的数是val ,首先N--(因为一个人出圈)

 if(val>0) k=(k+val-2)%N+1,下一个相对于该人的位置是 K+val,但是该人出队以后,下一个就会前移一个位置,所以减一,然后位置1~N,还涉及到对N取余,(取余后0~N-1),所以括号里面减一,加在外面。相应的,if(val<0) k=((k+val-1)%N+N)%N+1;  跟poj 2828都属于查找吧

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 500005
using namespace std;
struct Node
{
    char name[12];
    int val,num,l,r;
}node[nMAX*4];
int n,k,cnt,dest,x;
char ans[12];
int antiPrim[40]={1,2,4,6,12,24,36,48,60,120,180,240,360,
 720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,
 27720,45360,50400,55440,83160,110880,166320,221760,277200,
 332640,498960,554400,665280},
factor[40]={1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,
 48,60,64,72,80,84,90,96,100,108,120,128,144,160,168,180,
 192,200,216,224};
void create(int l,int r,int u)
{
    node[u].l=l,node[u].r=r;
    if(l==r)
    {
        scanf("%s%d",&node[u].name,&node[u].val);
        node[u].num=1;
        return ;
    }
    int mid=(r+l)/2;
    create(l,mid,2*u);
    create(mid+1,r,2*u+1);
    node[u].num=node[2*u].num+node[2*u+1].num;
}
void update(int u,int order)
{
    node[u].num--;
    if(node[u].l==node[u].r)
    {
        if(order==antiPrim[dest])
        {
            strcpy(ans,node[u].name);
        }
        else
        {
            n--;
            if(node[u].val>0){k=(k+node[u].val-1-1)%n+1;}
            else {k=((k+node[u].val-1)%n+n)%n+1;}
        }
        return ;
    }
    if(x<=node[2*u].num)update(2*u,order);
    else
    {
        x-=node[2*u].num;
        update(2*u+1,order);
    }
}
int main()
{
    int i;
    while(~scanf("%d%d",&n,&k))
    {
        create(1,n,1);
        for(i=0;i<35;i++)
        {
            if(n>=antiPrim[i]&&n<antiPrim[i+1])
                dest=i;
        }
        int PP=n;
        for(i=1;i<=antiPrim[dest];i++)//进行antiPrim[dest]次就可以了
        {
            x=k;
            update(1,i);
        }
        printf("%s %d\n",ans,factor[dest]);
    }
    return 0;
}

  

posted @ 2012-08-13 21:58  快乐.  阅读(173)  评论(0编辑  收藏  举报