牛客练习赛14 B.区间的连续段(前缀和 倍增)

简介: 牛客练习赛14 B.区间的连续段(前缀和 倍增)

原题链接

题意:

给你一个长为n的序列a和一个常数k。有m次询问,每次查询一个区间[ l , r ]内所有数最少分成多少个连续段,使得每段的和都< = k。如果这一次查询无解,输出" C h t h o l l y "。

思路:

先考虑简化版:给定一个序列和k,问将该序列最少分成多少个连续段,使得每段的和都< = k。

从前向后枚举,对于每次结果都贪心的考虑,如果当前和大于k就重新开一段。

也就是说需要处理的就是,对于每个点能够到达的最远的点。

回到这个题,类比的处理一下。但是加了区间限制之后,最远的点不一定在区间里,所以略微变形一下:维护d p [ i ] [ j ]表示从点i开始,分成2 j段,最远能够到达的位置的下一个点。

由于2 j = 2 j − 1 + 2 j − 1,所以d p [ i ] [ j ] = d p [ d p [ i ] [ j − 1 ] ] [ j − 1 ]

对于d p [ i ] [ 0 ] = x,找一个位置[ i , x − 1 ]使得该段的和恰好小于k kk;s u m [ i ] sum[i]sum[i]表示a aa的前缀和。也就是说s u m [ x − 1 ] − s u m [ i − 1 ] < k , s u m [ x − 1 ] < s u m [ i − 1 ] + k sum[x-1]-sum[i-1]

对于查询:" C h t h o l l y "的情况就是a [ i ] > k , l < = i < = r。用t o t [ i ]表示前i个数中> k的数的个数,每次查询t o t [ r ] − t o t [ l − 1 ],如果大于0,就是" C h t h o l l y "

对于其他情况,从大到小枚举,类似二进制拆分的原理。[ l , s t [ l ] [ i ] )表示将区间分成了2 i段,所以答案要加2 i 。

注意d p维护的是下一个位置,所以最后那段是不计算的,要额外再+ 1

代码:

const int maxn=1000000+7;
ll n,m,k,a[maxn],tot[maxn];
ll dp[maxn][25];
ll sum[maxn];
int main(){
  n=read,m=read,k=read;
  rep(i,1,n){
    a[i]=read;
    sum[i]=sum[i-1]+a[i];
    if(a[i]>k) tot[i]=tot[i-1]+1;
    else tot[i]=tot[i-1];
  }
  rep(i,1,n){
    dp[i][0]=upper_bound(sum+1,sum+1+n,sum[i-1]+k)-(sum+1)+1;
  }
  for(int j=1;(1<<j)<n;j++)
    for(int i=1;i+(1<<j)<=n;i++){
      dp[i][j]=dp[dp[i][j-1]][j-1];
    }
  while(m--){
    int l=read,r=read;
    if(tot[r]-tot[l-1]>0){
      puts("Chtholly");
    }
    else{
      int res=1;
      for(int i=20;dp[l][0]<=r;i--)
        if(dp[l][i]&&dp[l][i]<=r)
          l=dp[l][i],res+=(1<<i);
      cout<<res<<endl;
    }
  }
  return 0;
}


目录
相关文章
|
9月前
|
人工智能 算法
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
|
9月前
每日一题(最大连续1的个数,完全数计算)
每日一题(最大连续1的个数,完全数计算)
42 0
|
9月前
|
人工智能 算法 Java
最长连续不重复子序列(蓝桥杯每日一题)
最长连续不重复子序列(蓝桥杯每日一题)
64 0
【力扣每日一题:2-19】1004. 最大连续1的个数 III【中等】
【力扣每日一题:2-19】1004. 最大连续1的个数 III【中等】
|
人工智能 算法
代码随想录算法训练营第三十五天 | LeetCode 435. 无重叠区间、763. 划分字母区间、56. 合并区间
代码随想录算法训练营第三十五天 | LeetCode 435. 无重叠区间、763. 划分字母区间、56. 合并区间
78 0
|
人工智能
蓝桥 k倍区间 (前缀和)
蓝桥 k倍区间 (前缀和)
|
机器学习/深度学习 算法 Java
刷爆 LeetCode 周赛 337,位掩码/回溯/同余/分桶/动态规划·打家劫舍/贪心
上周末是 LeetCode 第 337 场周赛,你参加了吗?这场周赛第三题有点放水,如果按照题目的数据量来说最多算 Easy 题,但如果按照动态规划来做可以算 Hard 题。
133 0
Leetcode-每日一题769. 最多能完成排序的块(贪心)
需要怎么分割序列才是个问题,题目其实给了提示因为序列里的数只能是[0, n-1]所以选择[l, r] 连续的序列中的数一定是 [l, r] 这段区间的数字,所以我们只需要遍历数组,去找这段区间内最大的数字,即边界值r,因为他才是决定边界的数字,每次我们到达了r这个位置就表示下一段区间。
81 0
Leetcode-每日一题769. 最多能完成排序的块(贪心)
【八月】 每日一题 - 768. 最多能完成排序的块 I and II
【八月】 每日一题 - 768. 最多能完成排序的块 I and II
111 0
【八月】 每日一题 - 768. 最多能完成排序的块 I and II
|
存储 机器学习/深度学习 人工智能
【Python 百练成钢】DNA、蛇形矩阵、Huffuman树、K-进制数、K倍区间、交换瓶子、第几个幸运数、四平方和、The 3n + 1 problem、大数乘法
【Python 百练成钢】DNA、蛇形矩阵、Huffuman树、K-进制数、K倍区间、交换瓶子、第几个幸运数、四平方和、The 3n + 1 problem、大数乘法
【Python 百练成钢】DNA、蛇形矩阵、Huffuman树、K-进制数、K倍区间、交换瓶子、第几个幸运数、四平方和、The 3n + 1 problem、大数乘法