POJ - 2886线段树+线性筛
题意就是给你n个人,每个人有一个名字和A,如果A为正则向左找第A个,否则向右找第-A个,每找到一个就出列,然后第i个人出列的F(i)是i的所有因子个数
输出最大的F(i)和对应的名字
先用线性筛找出第几个出列的值最大maxn,那么求到maxn就可以了。
用线段树记录空位,k表示当前需要从剩余人第几个位置寻找,只要推出k,则转化为线段树的求位置的模型
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=500010; char name[N][15]; int pos[N]; int cnt[N]; struct node { int l,r; int spare; } seg[N<<2]; void pushup(int rt) { seg[rt].spare=seg[2*rt].spare+seg[2*rt+1].spare; } void build(int rt,int L,int R) { seg[rt].l=L; seg[rt].r=R; seg[rt].spare=1; if(L==R) { return; } int mid=(seg[rt].l+seg[rt].r)/2; build(2*rt,L,mid); build(2*rt+1,mid+1,R); pushup(rt); } int index; void update(int rt,int val) { if(seg[rt].l==seg[rt].r) { index = seg[rt].l; seg[rt].spare=0; return; } if(seg[2*rt].spare>=val) update(2*rt,val); else update(2*rt+1,val-seg[2*rt].spare); pushup(rt); } int slove(int n)//线性筛求最大 { int maxcnt=-0x3f3f3f3f; int maxn; memset(cnt,0,sizeof(cnt)); for (int i=1; i<=n ; i++ ) { cnt[i]++; for (int j=2*i; j<=n ; j+=i ) cnt[j]++; } for (int i=1; i<=n ; i++ ) { if(cnt[i]>maxcnt) { maxcnt=cnt[i]; maxn=i; } } return maxn; } int main() { int n,k; while(~scanf("%d%d",&n,&k)) { int maxn=slove(n); for (int i=1; i<=n ; i++ ) { scanf("%s %d",name[i],&pos[i]); } build(1,1,n); int mod=seg[1].spare; pos[0]=0; index=0; for (int i=1; i<=maxn; i++ ) { if(pos[index]>0) { k=(k-1+pos[index]-1)%mod+1; } else { k=((k+pos[index]-1+mod)%mod+mod)%mod+1; } update(1,k); mod=seg[1].spare; } printf("%s %d\n",name[index],cnt[maxn]); } return 0; }