2021-04-26 06:13阅读: 141评论: 0推荐: 1

牛客练习赛14B 区间的连续段

题目链接

点我跳转

题目大意

给定一个长度为 N 的序列 A 和一个常数 K

M 次询问

每次询问查询一个区间 [L,R] 内所有数最少分成多少个连续段

使得每段的和都 <=K ,若无解则输出 "Chtholly"

解题思路

简单回忆一下倍增求 LCA 思想:

  • f[i][j] 表示以 i 为起点,往上跳 i+2j 步后得到的祖先
  • 因为往上跳 2j 等价于先往上跳 2j1 步后再往上跳 2j1
  • 所以可得: f[i][j]=f[f[i][j1]][j1]

回到这道题:

暴力的做法即遍历区间 [l,r] ,贪心的让每段的长度尽可能大

考虑用倍增思想优化:

定义 f[i][j] 表示:

i 为起点,分成 2j 个连续段后,所能到达的最远位置的下一个位置(其中每个段的和都不超过 K

那么不难得到: f[i][j]=f[f[i][j1]][j1]f[i][0] 可通过二分前缀和得到

然后对于每个询问 (L,R)

先判断区间 [L,R] 是否存在 Ai 使得 Ai>K

这步我们维护一个权值数组的前缀和 O1 判断

即当 Ai<=K 时,sum[i]=sum[i1]

Ai>K时,sum[i]=sum[i1]+1

sum[R]sum[L1]>0 则表示该区间存在 Ai>K,直接输出 Chtholly

sum[R]sum[L1]=0 则从高位往低位枚举 j

如果 f[L][j]>R 则表示从 L 开始划分出 2j 个连续段是 OK
但是 2j 连续段可能太多了(题目要求划分的连续段个数最少
所以就继续往下枚举

如果 f[L][j]<R,则表示从 L 开始划分出 2j 个连续段是不够的
那就先划分出 2j 个连续段,然后再从 f[L][j] 的位置继续划分
ans+=1<<jL=f[L][j]

AC_Code

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

int f[N][22];

int n , m , k , a[N] , sum[N];

long long pre[N];

signed main()
{
	cin >> n >> m >> k;
	
	for(int i = 1 ; i <= n ; i ++)
	{
		cin >> a[i] , pre[i] = pre[i - 1] + a[i];
		
		sum[i] = sum[i - 1] + (a[i] > k); 
	}
	for(int j = 0 ; j <= 21 ; j ++) f[n + 1][j] = n + 1;
	
	for(int j = 0 ; j <= 21 ; j ++)
	{
		for(int i = 1 ; i <= n ; i ++)
		{
			f[i][0] = upper_bound(pre + i , pre + 1 + n , k - a[i] + pre[i]) - pre;
			
			if(!j) continue ;
			
			f[i][j] = f[f[i][j - 1]][j - 1]; 
		}
	}
	while(m --)
	{
		int l , r , ans = 0;
		
		cin >> l >> r;
		
		if(sum[r] - sum[l - 1]) 
		{
			cout << "Chtholly\n";
			
			continue ;
		}
		for(int j = 21 ; j >= 0 ; j --)
		{
			if(f[l][j] - 1 < r) 
			{
				ans += 1 << j;
				
				l = f[l][j];
			}
		}
		cout << ans + 1 << '\n';
	}
	return 0;
}

本文作者:GsjzTle

本文链接:https://www.cnblogs.com/GsjzTle/p/14702955.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   GsjzTle  阅读(141)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
阅读排行:
· 一个适用于 .NET 的开源整洁架构项目模板
· API 风格选对了,文档写好了,项目就成功了一半!
· 【开源】C#上位机必备高效数据转换助手
· .NET 9.0 使用 Vulkan API 编写跨平台图形应用
· MyBatis中的 10 个宝藏技巧!
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 アゲイン 横山克
  2. 2 私の嘘 横山克
アゲイン - 横山克
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.