poj2886Who Gets the Most Candies?

来源:互联网 发布:凸优化理论与应用 编辑:程序博客网 时间:2024/05/22 06:33

这道题又加深了我对线段树的认识,不过依然被自己坑的很惨,简直不能忍。

题意不难理解,用线段树来快速找到从当前开始的第k个人,注意公式推导一定要认真。最郁闷的是,自己的约数算法是错的。。。愚蠢的写成了i j都小于770,实际上有些数的约数可能大于根号500000.。。

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const int MAX=500010;int table[MAX],n,k,val[MAX],segtree[MAX*4];char name[MAX][20];void push(int which){    segtree[which]=segtree[which<<1]+segtree[which<<1|1];}void build(int which,int front,int rear){    if(front==rear){        segtree[which]=1;        return ;    }    int mid=(front+rear)>>1;    build(which<<1,front,mid);    build(which<<1|1,mid+1,rear);    push(which);}int get(int num,int which,int front,int rear){    if(front==rear){        segtree[which]=0;        //printf("%db",front);        return front;    }    int ret,mid=(front+rear)>>1;    if(segtree[which<<1]>=num){        //printf("test");        ret=get(num,which<<1,front,mid);    }    else        ret=get(num-segtree[which<<1],which<<1|1,mid+1,rear);    push(which);    return ret;}int main(){    /*table[1]=1;    for(int i=2;i<MAX;i++)        table[i]=2;    for(int i=2;i<=770;i++)        for(int j=2;i*j<=MAX;j++){                if(i*j==1542)                printf("%d %d\n",i,j);                table[i*j]++;        }*/    int limit=(int)sqrt(MAX*1.0);    for(int i=1; i<=limit; ++i)    {        for(int j=i+1; j*i<=MAX; ++j)            table[i*j]+=2;        table[i*i]++;    }    //for(int i=1;i<10000;i++)       //printf("%d\n",table[1542]);    int maxx;    char names[20];    while(scanf("%d %d",&n,&k)!=EOF){        build(1,1,n);        int left=n-1;        maxx=0;        for(int i=1;i<=n;i++){            scanf("%s %d",name[i],&val[i]);        }        /*if(k>0){这部分不需要考虑            if(k%n!=0)                k%=n;            else                k=n;        }        else{            if(k%n!=0){                k%=n;            }            else                k=-n;            k+=n+1;        }*/        for(int i=1;i<=n;i++){            int num=get(k,1,1,n);            //printf("%d ",num);            if(table[i]>maxx){                maxx=table[i];                strcpy(names,name[num]);            }            if(i==n)//i等于n时会发生对0取余的错误                break;                if(val[num]>0){                k=k+val[num]-1;                if(k%left!=0)                    k%=left;                else                    k=left;            }            else{                int help=left-k+1-val[num];                if(help%left!=0)                    help%=left;                else                    help=left;                k=left-help+1;            }            //printf("k%d",k);            left--;            //printf("a");        }        printf("%s %d\n",names,maxx);    }    return 0;}


0 0