poj 2886(线段树单点更新)

poj 2886


题意:

有N个人,顺时针围成一个圈,现指定第K个人先跳出,然后报一个数A,A>0,表示从跳出的人(跳出的人不算)左边第一个人开始的第A个人跳出,A<0,则相反,且之后跳出的人进行相同的步奏,现要求的是第i个人跳出时,满足当前i的因子数最多且因子数一样时越早跳出越好。


解题思路:

首先我们可以算出当前如果有N个人它的反素数(<=N,且因子数最多并且最小),然后当一个人跳出时,我们可以算出这个人得左和右各有多少人,这样我们可以求出当前为A时,下一个人在当前总人数的倒数第几个,然后利用线段树去找对应的位置,并更新即可。

注意:

反素数可以利用dfs求

网站:点击打开链接

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
typedef int  int64;
#define MAXN0 500010
#define l1(x) (x<<1)
#define l2(x) (l1(x)+1)
#define r1(x) ((x)>>1)
char na[MAXN0][15];
int way[MAXN0],cnt,p[800];
bool vis[800];
int ans,cnter;
struct yznode{
    int num,yz;
};
yznode yzmax[MAXN0];
struct node{
    int L,R,C;
    void setLRC(int aa,int bb){
        L = aa;
        R = bb;
        // C = cc;
    }
};
node TR[MAXN0<<2];
int64 prime[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
void dfs(int64 cur,int64 cnt,int64 power,int64 sub,int n)
{
    int64 i;
    if(cur>n)
        return;
    if(cnt==cnter&&cur<ans)
        ans=cur;
    if(cnt>cnter)
    {
        ans=cur;
        cnter=cnt;
    }
    int64 p=prime[sub];
    for(i=1;i<=power;i++)
    {
        if(cur*p>n)
            break;
        dfs(cur*p,cnt*(i+1),i,sub+1,n);
        p=p*prime[sub];
    }
}
void buildTR(int ind,int L,int R){
    TR[ind].setLRC(L, R);
    if(L==R){
        TR[ind].C = 1;
        return;
    }
    int mid = r1(L+R);
    int ind1 = l1(ind);
    int ind2 = ind1+1;
    buildTR(ind1, L, mid);
    buildTR(ind2, mid+1, R);
    TR[ind].C = TR[ind1].C+TR[ind2].C;
}
void pushup(int ind,int ind1,int ind2){
    TR[ind].C = TR[(ind1)].C+TR[(ind2)].C;
}
//int update(int ind,int K){
//    if(TR[ind].L==TR[ind].R){
//        if(TR[ind].L==K){
//            TR[ind].C = 0;
//        }
//        return 0;
//    }
//    int mid = r1(TR[ind].L+TR[ind].R),H=0;
//    if(mid>=K){
//         H = update(l1(ind),K) + TR[l2(ind)].C;
//       // pushup(ind);
//    }
//    else {
//         H =   update(l2(ind), K);
//
//    }
//    pushup(ind);
//    return H;
//}
int Query(int ind,int F){
    if(TR[ind].L==TR[ind].R){
        // TR[ind].C = 0;
        TR[ind].C = 0;
        return TR[ind].L;
        
        //return 0;
    }
    int H;
    int ind1,ind2;
    ind1 = (l1(ind));
    ind2 = (ind1+1);
    if(TR[ind2].C>=F){
        
        H =   Query(ind2,F);
    }
    else {
        H =  Query(ind1,F - TR[ind2].C);
    }
    pushup(ind,ind1,ind2);
    return H;
}
void solve(int N,int K){
    int ind = ans;
    //int nn = yzmax[N].num;
    //int cnt = 0;
    int tmpN = N;
    int tmp0,tmp1,tmp2,tmp3,tmp4,tmp8;
    int cc = 1;
    --tmpN;
    //tmp0  = Query(1,N-K+1);//当前在K右边的总数
    //tmp1 = tmpN - tmp0;
    if(N!=1){
        Query(1, N-K+1);
        tmp0 = N - K ;
        tmp1 = K - 1;
    }
    while(cc<ind){
        tmp8 = abs(way[K])%tmpN;
        if(!tmp8)tmp8+=tmpN;
        if(way[K]<0){
            if(tmp0==0||tmp1==0){
                tmp4 = tmp8;
            }
            else{
                if(tmp8<=tmp1){
                    tmp4 = tmp0 + tmp8;
                }
                else {
                    tmp4 = tmp8 - tmp1;
                }
            }
        }
        else {
            if(tmp0==0||tmp1==0){
                tmp4 = tmpN - tmp8 + 1;
            }
            else{
                if(tmp8<=tmp0){
                    tmp4 = tmp0 - tmp8 + 1;
                }
                else {
                    tmp4 = tmpN + tmp0 - tmp8 + 1 ;
                }
            }
        }
        K = Query(1,tmp4);
        --tmpN;
        //int tmp6 = tmp0;
        tmp0 = tmp4 -1;
        tmp1 = tmpN - tmp0;
        ++cc;
    }
    printf("%s %d\n",na[K],cnter);
}
int main(){
    int N,K;
    //getpr();
    //prepro();
    while(scanf("%d%d",&N,&K)!=EOF){
        buildTR(1,1,N);
        for(int i=1;i<=N;++i){
            scanf("%s%d",na[i],&way[i]);
        }
        cnter = 0,ans = 0;
        dfs(1,1,50,0,N);
        solve(N,K);
        //}
    }
    return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值