poj2886 Who Gets the Most Candie…

题意:N个人围成一圈第一个人跳出圈后会告诉你下一个谁跳出来跳出来的人(如果他手上拿的数为正数,从他左边数A个,反之,从他右边数A个) 跳出来的人所得到的糖果数量和他跳出的顺序有关 所得的糖果数为 (假设他是第k个跳出的) 则他得到的糖数为k能被多少个数正数 比如说 k = 6 ;  6 = 1*2*3*6 所以他得到的糖数为4;

思路:线段数 先算出N个人中,是第几个人(id)跳出来得到的糖果最多。然后模拟id遍 长到第id个人的name
线段树的结点中保存该区间内还剩多少人,每次update 删除一个人。

//24200K      1235MS
#include <stdio.h>
#include <string.h>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
const int M = 500010;
int n,id;
struct tree
{
      int l,r,sum; //sum 表 该区间剩余人数
} node[M*3];

struct data
{
      int val;
      char name[15];
} boy[M];

int ans[M]; //ans[i]保存第i个人跳出能得到的糖果数量

void BuildTree (int left,int right,int u)
{
      node[u].l = left;
      node[u].r = right;
      node[u].sum = right - left + 1;
      if (left == right)
              return ;
      int mid = (left + right)>>1;
      BuildTree(left,mid,L(u));
      BuildTree(mid+1,right,R(u));
}
int update (int key,int u)
{
      node[u].sum --;
      if (node[u].l == node[u].r)
              return node[u].l;
      if (node[L(u)].sum >= key)
              return update(key,L(u));
      else
              return update (key - node[L(u)].sum,R(u));
}
void count_ans()
{
      memset (ans,0,sizeof(ans));    //计算ans
      for (int i = 1; i <= n; i ++)
      {
              ans[i] ++;
              for (int j = 2*i; j <= n; j += i)
                      ans[j] ++;
      }
      int max = ans[1];
      id = 1;
      for (int i = 2; i <= n; i ++) //找出第几个人跳出获得的糖最多
              if (ans[i] > max)
              {
                      max = ans[i];
                      id = i;
              }
}
int main ()
{
      int i,k,mod;
      while (~scanf ("%d %d",&n,&k))
      {
              count_ans();
              for (i = 1; i <= n; i ++)
                      scanf ("%s %d",boy[i].name,&boy[i].val);
              BuildTree (1,n,1);
              mod = node[1].sum;
              int pos = 0;
              boy[0].val = 0;
              n = id;
              while (n --)
              {
                      if (boy[pos].val > 0)  //k表剩余的人中从左起第k中出队(PS:k的求法是看别人的)
                              k = ((k + boy[pos].val - 2)%mod + mod)%mod + 1;
                      else
                              k = ((k + boy[pos].val - 1)%mod + mod)%mod + 1;
                      pos = update(k,1);
                      mod = node[1].sum;
              }
              printf ("%s %d\n",boy[pos].name,ans[id]);
      }
      return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值