poj 2886(线段树单点更新)
来源:互联网 发布:seo经验分享 编辑:程序博客网 时间:2024/05/01 21:31
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;}
0 0
- poj 2886(线段树单点更新)
- POJ 2886 线段树单点更新+数论
- poj 2886 线段树 单点更新
- poj 2828 线段树单点更新
- POJ 2481 Cows(线段树[单点更新])
- POJ 2828(线段树 单点更新)
- POJ 2352 线段树(单点更新)
- poj 2828 线段树 单点更新
- 【poj】2481 Cows【线段树单点更新】
- POJ 2828 (线段树-单点更新)
- POJ 2828 线段树单点更新
- poj 2828(线段树单点更新)
- poj 2828 线段树+单点更新
- poj 2481 Cows【线段树单点更新】
- POJ 2828 线段树 单点更新,单点查询
- 线段树 单点更新
- 线段树单点更新
- 线段树 单点更新
- linux基本指令
- TINY4412 驱动开发学习笔记整理--环境搭建篇
- 字符串-02. 删除字符串中的子串(20)
- boj408字符串——hash的应用
- 转载的面试题
- poj 2886(线段树单点更新)
- [UvaLive 6757] Cup of Cowards [搜索]
- CSDN好久不上交流请加加入QQ群114744191
- renderer.material.mainTexture,
- 蜘蛛侠从天而降,摔死在我的mac键盘上
- bootstrap之MultiPointerGesture
- Android ListView加载两种不同的item
- 用一条insert 插入多行数据的方法
- Unity3d之截图方法