zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    SQLite 基本使用
    SQLite 语法
    html5晋级之路-css介绍
    html5晋级之路-web storage
    html5晋级之路-元素语法
    html晋级之路-背景、实体
    ios-晋级之路 CocoaPods的使用
    如何在Mac OS X上安装 Ruby运行环境
    html5晋级之路-学习笔记表单
    html5晋级之路-学习笔记
  • 原文地址:https://www.cnblogs.com/liulangye/p/2546662.html
Copyright © 2011-2022 走看看