poj 3750 小孩报数问题(线段树-单点更新)

来源:互联网 发布:用爸妈身份证开淘宝店 编辑:程序博客网 时间:2024/05/23 12:31

Description

有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。

Input

第一行输入小孩的人数N(N<=64) 
接下来每行输入一个小孩的名字(人名不超过15个字符) 
最后一行输入W,S (W < N),用逗号","间隔

Output

按人名输出小孩按顺序出列的顺序,每行输出一个人名

Sample Input

5XiaomingXiaohuaXiaowangZhangsanLisi2,3

Sample Output

ZhangsanXiaohuaXiaomingXiaowangLisi

这道题用模拟和链表可以做,也是练习链表的题,鉴于我是渣渣线段树能力,这里用线段树再做一遍(就是上一道题的简化版)

#include <iostream>#include <stdio.h>#include <string.h>#include <queue>using namespace std;#define maxn 100struct node{    char name[15];  //  int val;  //记录val}num[maxn*3];int Count[maxn*3];  //记录人数void PushUp(int root){    Count[root]=Count[root<<1]+Count[(root<<1)+1];}void Build(int L,int R,int root){    Count[root]=R-L+1;    if(L==R)        return;    int mid=(L+R)>>1;    Build(L, mid, root<<1);    Build(mid+1, R, (root<<1)+1);}int Update(int pos,int L,int R,int root){    if(L==R)    {        Count[root]--;        return L;    }    int mid=(L+R)>>1;    int ans;    if(pos<=Count[root<<1])       ans=Update(pos, L, mid, root<<1);    else       ans=Update(pos-Count[root<<1], mid+1, R, (root<<1)+1);    PushUp(root);    return ans;    }int main(){    int n,w,s,k,pos;    while (scanf("%d",&n)!=EOF)    {        for (int i=1; i<=n; i++)        {            scanf("%s",num[i].name);            getchar();        }        scanf("%d,%d",&w,&s);        Build(1, n, 1);        k=w;        for (int i=1; i<=n && Count[1]; i++)        {            k=((k+s-2)%Count[1]+Count[1])%Count[1]+1;            pos=Update(k,1,n,1);            printf("%s\n",num[pos].name);        }            }    return 0;}



0 0
原创粉丝点击