【Removing Stones 】

本文介绍了一种解决特定区间问题的算法思路——启发式分治法。该方法通过枚举区间的最大值,利用分治策略找到满足条件的区间两端,并结合二分查找优化搜索过程,有效地解决了区间最大值的两倍小于等于区间和的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.牛客多校的题目,大意就是:找出有多少个区间满足:区间最大值的两倍小于等于区间和。统计这样的区间数并输出答案。

2.我们可以枚举最大值,对于每个a[i],他都可以作为某些区间的最大值,可以找出这段区间最左边的端点和最右边的端点。然后枚举一个二分另外一个即可。至于怎么枚举最值,可以分治,分治的时候会出现一些比较强的数据,让你的分治失效,如果你每次都是默认的枚举左端点二分右端点,那么可能区间不是很理想,我们肯定是要二分大的区间,枚举小的区间,所以在分治的过程中,有选择的枚举即可。这也叫做启发式分治。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 3e5 + 10;

int a[maxn], n, dp[maxn][25], pos[maxn][25];
long long pre[maxn], suf[maxn];

void init()
{
	for (int i = 1; i <= n; i++) dp[i][0] = a[i], pos[i][0] = i;
	for (int j = 1; (1 << j) <= n; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) {
		if (dp[i][j - 1] >= dp[i + (1 << (j - 1))][j - 1]) dp[i][j] = dp[i][j - 1], pos[i][j] = pos[i][j - 1];
		else dp[i][j] = dp[i + (1 << (j - 1))][j - 1], pos[i][j] = pos[i + (1 << (j - 1))][j - 1];
	}
}

int query(int l, int r)
{
	int k = 0;
	while (l + (1 << (k + 1)) - 1 <= r) k++;
	if (dp[l][k] >= dp[r - (1 << k) + 1][k]) return pos[l][k];
	return pos[r - (1 << k) + 1][k];
}

ll dfs(int l, int r)
{
	if (l >= r) return 0;
	int max_pos = query(l, r); 
	ll res = 0;
	if (max_pos - l < r - max_pos)
		for (int i = l; i <= max_pos; i++) 
			res += r - (lower_bound(pre + max_pos, pre + r + 1, pre[i - 1] + 2 * a[max_pos]) - pre - 1);
	else 
		for (int i = max_pos; i <= r; i++)
			res += (n - l + 1) - (lower_bound(suf + n - max_pos + 1, suf + n - l + 2, suf[n - i] + 2 * a[max_pos]) - suf - 1);
	return res + dfs(l, max_pos - 1) + dfs(max_pos + 1, r);
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--) 
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i], suf[i] = suf[i - 1] + a[n - i + 1];
		init();
		printf("%lld\n", dfs(1, n));
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值