• poj 2886 Who Gets the Most Candies?


    http://poj.org/problem?id=2886

      一道借助线段树找出第k个位置的题。

      题意是,有n个人,他们手中拿着一张写着不为零的数的牌。开始的时候是从第k个人开始的,数到的人出列,然后从那个人的位置开始数d个人,d是他手上的牌的数字,数到的下一个出列,如此反复。第i个出列的人可以得到F(i)个糖果,F(i)是因数的个数。

      这题主要问题在计算下一个人的位置时,如果next(也就是这个人手上拿的数)是负数的话,就要调整一下位置,因为这时的-1相当于是0了。然后质因数,就直接预处理一下,其他的都没什么大问题了。没调整负数的情况,wa了一次。。。

    代码如下:

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdlib>
     5 
     6 #define lson l, m, rt << 1
     7 #define rson m + 1, r, rt << 1 | 1
     8 
     9 using namespace std;
    10 
    11 const int maxn = 500005;
    12 int cntFac[maxn], maxCnt[maxn];
    13 
    14 void pre() {
    15     for (int d = 1; d < maxn; d++) {
    16         for (int i = d; i < maxn; i += d) {
    17             cntFac[i]++;
    18         }
    19     }
    20     for (int i = 1; i < maxn; i++) {
    21         maxCnt[i] = (cntFac[maxCnt[i - 1]] >= cntFac[i]) ? maxCnt[i - 1] : i;
    22     }
    23 //    for (int i = 0; i < 20; i++) {
    24 //        printf("%d : %d %d\n", i, cntFac[i], maxCnt[i]);
    25 //    }
    26 }
    27 
    28 int rec[maxn], cnt[maxn << 2];
    29 char name[maxn][12];
    30 
    31 void up(int rt) {
    32     cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
    33 }
    34 
    35 void build(int l, int r, int rt) {
    36     if (l == r) {
    37         cnt[rt] = 1;
    38         return ;
    39     }
    40     int m = (l + r) >> 1;
    41 
    42     build(lson);
    43     build(rson);
    44     up(rt);
    45 }
    46 
    47 int locate(int _p, int l, int r, int rt) { // the k-th person, begin from 1
    48     if (l == r) {
    49         cnt[rt] = 0;
    50         return l;
    51     }
    52     int m = (l + r) >> 1, ret;
    53 
    54     if (_p <= cnt[rt << 1]) ret = locate(_p, lson);
    55     else ret = locate(_p - cnt[rt << 1], rson);
    56     up(rt);
    57 
    58     return ret;
    59 }
    60 
    61 int calNext(int cur, int next, int size) {
    62     if (next < 0) next++;
    63     return (((cur + next - 1) % size) + size - 1) % size + 1;
    64 }
    65 
    66 int deal(int n, int k) {
    67     int ret = 0, tmp = 0;
    68 
    69     build(1, n, 1);
    70     rec[0] = k + 1;
    71 //    printf("%d\n", maxCnt[n]);
    72     for (int i = 0, endi = maxCnt[n]; i < endi; i++) {
    73         ret = calNext(ret, rec[tmp], n - i);
    74         tmp = locate(ret, 1, n, 1);
    75 //        printf("ret %d\n", ret);
    76 //        printf("tmp %d\n", tmp);
    77 //        puts("~~~");
    78     }
    79 
    80     return tmp;
    81 }
    82 
    83 int main() {
    84     int n, k;
    85 
    86 //    freopen("in", "r", stdin);
    87     pre();
    88     while (~scanf("%d%d", &n, &k)) {
    89         for (int i = 1; i <= n; i++) {
    90             scanf("%s %d", name[i], &rec[i]);
    91         }
    92         printf("%s %d\n", name[deal(n, k)], cntFac[maxCnt[n]]);
    93     }
    94 
    95     return 0;
    96 }

    ——written by Lyon

  • 相关阅读:
    重置SQLSERVER表的自增列,让自增列重新计数
    【PLM】【PDM】60页PPT终于说清了PDM和PLM的区别;智造时代,PLM系统10大应用趋势!
    数据库设计规范
    不要听吹牛逼什么前端MVVM框架就是好,其实都是一帮没学好分层设计的搞出来的,让你彻底看清前端MVVM的本质
    SQL数据库日志清理
    1.3、安装MySQL、MySQLdb、Pycharm和其他软件
    1.2.2.3、Django虚拟目录作用以及文件说明
    nginx设置图片防盗链和白名单
    php-5.5.7升级,编译配置方法
    mysql函数CONCAT_WS()比CONCAT()更方便
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_2886_Lyon.html
Copyright © 2020-2023  润新知