• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

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

posted @ 2012-10-06 15:56  LyonLys  阅读(196)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3