zoukankan      html  css  js  c++  java
  • POJ_2886 Who Gets the Most Candies? 【二分+树状数组】

    一、题目

    POJ2886

    二、分析

      这个题目吧,开始没读懂,做的时候也没懂,WA的时候懂了。假设是第p个出圈的人有一个对应的因子个数$F(p)$,那么,题目求的就是这个$F(p)$最大的对应的人。

      1.首先要对所有$F(p)$值进行预处理打表。因为多次询问。

      2.每次都会有一个人出圈,那么为了能够每次方便的查到(新圈)第K个人的下标,需要对出圈的人进行处理,这里可以用树状数组,表示第pos个位置前还有多少个人在,如果不在,就对树状数组进行维护。需要注意的是树状数组需要初始化,即开始的时候每个人都是在自己的位置上的。

      3.确定K,确定K的时候,思路比较绕,画个图就明白了。总结一下,就是对于当前位置pos,对应的是当前圈的第K个人,那么下一时刻,他就出圈了。

      如果是他手里的数字是正,那么相当于从旧圈的第K-1个人开始考虑。

      如果手里的数字是负,因为新圈里,第K个人的位置被前一个圈的 K + 1个人顶替了,所以不用管。

      然后取余就可以了,注意细节就行。

      4.第K个人确定了,那么就需要找了,利用BIT的求和直接二分找就可以了。这里要注意找的是$F(p)$最大值对应的人。(最开始就是没注意这个WA了好多次)

    三、AC代码

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 
      7 const int MAXN = 5e5 + 100;
      8 
      9 struct Node
     10 {
     11     char s[15];
     12     int num;
     13 }Data[MAXN];
     14 
     15 int BIT[MAXN];
     16 int Prime[MAXN] = {0};
     17 int N, K, Ans, ID;
     18 
     19 void getPrime()
     20 {
     21     for(int i = 1; i < MAXN; i++)
     22     {
     23         for(int j = i; j < MAXN; j += i)
     24         {
     25             Prime[j]++;
     26         }
     27     }
     28 }
     29 
     30 void add(int x, int v)
     31 {
     32     while(x <= MAXN)
     33     {
     34         BIT[x] += v;
     35         x += x & -x;
     36     }
     37 }
     38 
     39 int sum(int x)
     40 {
     41     int ans = 0;
     42     while(x)
     43     {
     44         ans += BIT[x];
     45         x -= x & -x;
     46     }
     47     return ans;
     48 }
     49 
     50 int getPos(int t)
     51 {
     52     int left = 0, right = N, mid;
     53     while(left + 1 < right)
     54     {
     55         mid = (left + right) >> 1;
     56         if(sum(mid) < t)
     57             left = mid;
     58         else
     59             right = mid;
     60     }
     61     return right;
     62 }
     63 
     64 void solve()
     65 {
     66     int pos, temp;
     67     for(int i = N - 1; i > 0; i--)
     68     {
     69         pos = getPos(K);
     70         add(pos, -1);
     71         temp = Prime[N - i];
     72         if(Ans < temp)
     73         {
     74             Ans = temp;
     75             ID = pos;
     76         }
     77         if(Data[pos].num > 0)
     78         {
     79             K--;
     80         }
     81         K += Data[pos].num;
     82         K = (K%i + i) % i;
     83         if(K == 0)
     84             K = i;
     85     }
     86     K = getPos(K);
     87     temp = Prime[N];
     88     if(Ans < temp)
     89     {
     90         Ans = temp;
     91         ID = K;
     92     }
     93         
     94 }
     95 
     96 int main()
     97 {
     98     //freopen("input.txt", "r", stdin);
     99     getPrime();
    100     while(scanf("%d %d", &N, &K) != EOF)
    101     {
    102         memset(BIT, 0, sizeof(BIT));
    103         for(int i = 1; i <= N; i++)
    104         {
    105             add(i, 1);
    106             scanf("%s %d", Data[i].s, &Data[i].num);
    107         }
    108         Ans = 0;
    109         solve();
    110         printf("%s %d
    ", Data[ID].s, Ans);
    111     }
    112     return 0;
    113 }
  • 相关阅读:
    windows service 安装和卸载指令
    jackson 进行json与java对象转换 之四
    jackson 进行json与java对象转换 之三
    jackson 进行json与java对象转换 之二
    jackson 进行json与java对象转换 之一
    jackson2.x与Jackson1.9的比较
    判断Integer值相等不能用==
    java:String使用equals和==比较的区别
    Java中自定义枚举(Enum)项的值,可设置为指定的值
    Java enum(枚举)使用详解之四
  • 原文地址:https://www.cnblogs.com/dybala21/p/10536771.html
Copyright © 2011-2022 走看看