• hdu 3486 RMQ


    题意:有n个人排队应聘,每个人有一个能力值,然后老板要把这些人分成m段,如果不能整除多出来就后面的人就不要了,然后从这m段里面选择每段的最大能力值加起来看是否能够大于老板需要的目标k,因为薪资问题,尽可能少录取人,所以找出满足条件的最小的m。

    输入时找出所有能力值的最大值max,则分组最少为k/max(缩短时间,否则会TLE);然后枚举之后的分组,在每个分组内找最大值(RMQ),sum+=RMQ(L,R);当碰到第一个满足条件的分组时(sum>k),就可以跳出循环,直接输出答案了。

    RMQ一般用于求区间最值问题,但是也可以求类似区间gcd这种,不涉及到更新用RMQ会更快一点,否则还是用线段树。

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<math.h>
     4 #include<algorithm>
     5 #define LL long long
     6 
     7 using namespace  std;
     8 
     9 const int MAX_N = 200005;
    10 LL k,n;
    11 int num[MAX_N];
    12 int dp[MAX_N][20];
    13 
    14 void rmq_init()
    15 {
    16     for(int i = 0; i < n; i++)
    17         dp[i][0] = num[i];
    18     for(int j = 1; (1<<j) <= n; j++)
    19     {
    20         for(int i = 0; i+(1<<j)-1 < n; i++)
    21         {
    22             dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    23         }
    24     }
    25 }
    26 
    27 int rmq(int l,int r)
    28 {
    29     int k = 0;
    30     while(1<<(k+1)<=(r-l+1))
    31         k++;
    32     return max(dp[l][k],dp[r-(1<<k)+1][k]);
    33 }
    34 int main()
    35 {
    36     while(cin>>n>>k,n>0 || k>=0)
    37     {
    38         int maxx = 0,sum = 0;
    39         for(int i = 0; i < n; i++)
    40         {
    41             cin>>num[i];
    42             if(num[i]>maxx)
    43                 maxx = num[i];
    44             sum+=num[i];
    45         }
    46         if(sum<k)
    47         {
    48             cout<<-1<<endl;
    49             continue;
    50         }
    51         rmq_init();
    52         int zu = k / maxx;
    53         int peo,new_sum;
    54         if(zu==0)
    55             zu=1;
    56         for(;zu<=n;zu++)
    57         {
    58             peo = n/zu;
    59             new_sum = 0;
    60             for(int i = 1; i <= zu; i++)
    61             {
    62                 new_sum+=rmq((i-1)*peo,i*peo-1);
    63             }
    64             if(new_sum>k)
    65             {
    66                 break;
    67             }
    68         }
    69         cout<<zu<<endl;
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    32位和64位系统区别及int字节数
    进程的三种状态及转换
    已知二叉树的前序/后序遍历和中序遍历,求后序/前序遍历
    一步一步写算法
    Ubuntu中APache+mod_pyhon
    JAVA SOCKET
    TCP连接 断开
    mfc 创建一个C++ 类
    mfc 类的析构函数
    mfc 类对象的引用
  • 原文地址:https://www.cnblogs.com/Xycdada/p/7422109.html
Copyright © 2020-2023  润新知