zoukankan      html  css  js  c++  java
  • [POJ2886]Who Gets the Most Candies?

    题目:Who Gets the Most Candies?

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

    分析:

    1)这是一个约瑟夫环,关键在于如何定位下一个位置。如同楼层没有0层一样,针对card需要分正负讨论,计算出在新环中下一个离开的位置k。

    2)求出k在原环中的位置。采用数据结构维护一下。

    3)更新答案,移除小朋友,计算新的位置,直到结束。

    4)求反素数,用类似筛法的方式计算一下。当然也可以打表。

    5)有一个小优化,求出最优解所需的步数,就不用等到到全部小朋友都离开啦。

    方法一:二分+树状数组

    二分位置mid,树状数组维护 位置mid前 还有多少小朋友在现在的约瑟夫环中存在。

    更新答案并在树状数组中移除这个小朋友。

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int maxN=500005;
    char a[maxN+5][10];
    int n,b[maxN+5],f[maxN+5],T[maxN+5];
    void Tadd(int x,int y){for(int i=x;i<=n;i+=i&-i)T[i]+=y;}
    int Tque(int x){int ret=0;for(int i=x;i;i-=i&-i)ret+=T[i];return ret;}
    void Init(){
        for(int i=1,k=(int)(sqrt(double(maxN)+0.5));i<=k;++i){
            for(int j=i+1;j*i<=maxN;++j)f[j*i]+=2;
            ++f[i*i];
        }
    }
    int main(){
        Init();
        for(int k,ans0,ans1;~scanf("%d%d",&n,&k);){
            for(int i=1;i<=n;++i)T[i]=0;
            for(int i=1;i<=n;++i){scanf("%s %d",a[i],&b[i]);}
            for(int i=1;i<=n;++i)Tadd(i,1);
            ans1=0;
            for(int num=n,t=0;1;){
                int l=1,r=n,mid;
                for(;l<=r;){
                    mid=(l+r)>>1;
                    if(Tque(mid)<k)l=mid+1;else r=mid-1;
                }
                Tadd(l,-1);
                ++t;
                if(f[t]>ans1){ans0=l;ans1=f[t];}
                --num;
                if(!num)break;
                if(b[l]>0){
                    k=((k-2+num)%num+b[l])%num+1;
                }else{
                    k=((k+b[l]-1)%num+num)%num+1;
                }
            }
            printf("%s %d
    ",a[ans0],ans1);
        }
        return 0;
    } 

    方法二:线段树

    每个节点维护这个区间有多少小朋友,在线段树中寻找第k个小朋友的位置pos。

    更新答案并在线段树中移除这个小朋友。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxN=500005;
    char a[maxN+5][10];
    int n,pos,b[maxN+5],f[maxN+5];
    struct SegmentTree{
        int val[maxN<<2];
        void init(int v,int l,int r){
            if(l==r){val[v]=1;return;}
            int mid=(l+r)>>1;
            init(v<<1,l,mid);init((v<<1)+1,mid+1,r); 
            val[v]=val[v<<1]+val[(v<<1)+1];
        }
        void Modify(int v,int l,int r,const int &k){
            if(l==r){--val[v];pos=l;return;}
            int mid=(l+r)>>1;
            if(k<=val[v<<1])Modify(v<<1,l,mid,k);else Modify((v<<1)+1,mid+1,r,k-val[v<<1]);
            --val[v];
        }
    }T;
    void Init(){
        for(int i=1,k=(int)(sqrt(double(maxN)+0.5));i<=k;++i){
            for(int j=i+1;j*i<=maxN;++j)f[j*i]+=2;
            ++f[i*i];
        }
    }
    int main(){
        Init();
        for(int k,ans0,ans1;~scanf("%d%d",&n,&k);){
            memset(T.val,0,sizeof T.val);
            for(int i=1;i<=n;++i){scanf("%s %d",a[i],&b[i]);}
            T.init(1,1,n);
            ans1=0;
            for(int t=0,num;1;){
                T.Modify(1,1,n,k);
                ++t;
                if(f[t]>ans1){ans0=pos;ans1=f[t];}
                num=T.val[1];
                if(!num)break;
                if(b[pos]>0){
                    k=((k-2+num)%num+b[pos])%num+1;
                }else{
                    k=((k+b[pos]-1)%num+num)%num+1;
                }
            }
            printf("%s %d
    ",a[ans0],ans1);
        }
        return 0;
    } 

    PS:反素数表:

    int max_turn[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};
    int max_candy[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};
  • 相关阅读:
    IPC之msgutil.c源码解读
    IPC之msg.c源码解读
    IPC之mqueue.c源码解读
    从锅炉工到AI专家(10)
    从锅炉工到AI专家(9)
    从锅炉工到AI专家(8)
    从锅炉工到AI专家(7)
    从锅炉工到AI专家(6)
    从锅炉工到AI专家(5)
    从锅炉工到AI专家(4)
  • 原文地址:https://www.cnblogs.com/hjj1871984569/p/10347440.html
Copyright © 2011-2022 走看看