• POJ (线段树) Who Gets the Most Candies?


    这道题综合性挺强的,又牵扯到数论,又有线段树。

    线段树维护的信息就是区间中有多少个人没跳出去,然后计算出下一个人是剩下的人中第几个。

    我在这调程序调了好久,就是那个模来模去的弄得我头晕。

    不过题确实是好题,给赞。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cmath>
     4 #include <string>
     5 #include <algorithm>
     6 #include <vector>
     7 using namespace std;
     8 
     9 const int maxn = 500000 + 10;
    10 int n, k;
    11 int sum[maxn << 2];
    12 
    13 void build(int o, int L, int R)
    14 {
    15     if(L == R) { sum[o] = 1; return; }
    16     int M = (L + R) / 2;
    17     build(o*2, L, M);
    18     build(o*2+1, M+1, R);
    19     sum[o] = sum[o*2] + sum[o*2+1];
    20 }
    21 
    22 int update(int o, int L, int R, int p)
    23 {
    24     if(L == R) { sum[o] = 0; return L; }
    25     int M = (L + R) / 2;
    26     int ans;
    27     if(sum[o*2] >= p) ans = update(o*2, L, M, p);
    28     else ans = update(o*2+1, M+1, R, p-sum[o*2]);
    29     sum[o] = sum[o*2] + sum[o*2+1];
    30     return ans;
    31 }
    32 
    33 const int maxp = 750;
    34 int prime[maxp], pcnt = 0;
    35 bool vis[maxp];
    36 
    37 void prime_table()
    38 {
    39     int m = sqrt(maxp);
    40     for(int i = 2; i <= m; i++) if(!vis[i])
    41         for(int j = i * i; j < maxp; j += i) vis[j] = true;
    42     for(int i = 2; i < maxp; i++) if(!vis[i]) prime[pcnt++] = i;
    43 }
    44 
    45 int F(int n)
    46 {
    47     int ans = 1;
    48     for(int i = 0; i < pcnt && n > 1; i++) if(n % prime[i] == 0)
    49     {
    50         int c = 0;
    51         while(n % prime[i] == 0) { n /= prime[i]; c++; }
    52         ans *= c + 1;
    53     }
    54     if(n > 1) ans <<= 1;
    55     return ans;
    56 }
    57 
    58 int next[maxn];
    59 char stu[maxn][11];
    60 
    61 int main()
    62 {
    63     //freopen("in.txt", "r", stdin);
    64 
    65     prime_table();
    66 
    67     while(scanf("%d%d", &n, &k) == 2)
    68     {
    69         build(1, 0, n - 1);
    70         int _max = 0, id;
    71         for(int i = 0; i < n; i++) { scanf("%s%d", stu[i], &next[i]); }
    72 
    73         int pos = k - 1;
    74         for(int i = 1; i <= n; i++)
    75         {
    76             int t = update(1, 0, n - 1, pos + 1);
    77             int f = F(i);
    78             if(f > _max)
    79             {
    80                 _max = f;
    81                 id = t;
    82             }
    83             if(i == n) break;
    84             int MOD = n - i;
    85             if(next[t] < 0) next[t]++;  //负数的情况还要有一点小改动,在这坑了好久
    86             pos = (((pos + next[t] - 1) % MOD) + MOD) % MOD;
    87         }
    88         printf("%s %d
    ", stu[id], _max);
    89     }
    90 
    91     return 0;
    92 }
    代码君
  • 相关阅读:
    作业
    剑指Offer:链表中倒数第k个节点
    剑指Offer:反转链表
    剑指Offer:数值的整数次方
    剑指Offer:剪绳子Ⅰ和剪绳子Ⅱ
    剑指Offer:机器人的运动范围
    Linux下进程与线程的区别
    剑指Offer:调整数组顺序使奇数位于偶数前面
    剑指Offer:删除链表的节点
    剑指Offer:打印从1到最大的n位数
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4457677.html
Copyright © 2020-2023  润新知