sicily 1800 Sequence【线段树-RMQ】

题目链接:http://soj.me/1800

题目大意:给出一个序列a1, a2, a3,……an,求它的一个子序列使的这个子序列的和最小,并且这个子序列的长度只能在L和U之间。

对于这类子序列求和问题问法真是太多了,如果子序列长度没有上下界的话可以用动态规划来做,不过有上下界的时候,貌似没有想到动态规划的算法。

本题的思路大致如下:

首先求的整个序列的前缀和数组preSum[], 那么S[i, j]就可以表示为preSum[j]-preSum[i-1],那么本题需要求子序列最小和就可以通过从左到右扫描的方式来完成,对于当前位置i,只需要寻找到区间[max(0, i-U), i-L]的前缀和的最大值,那么 preSum[i]-preSum[j] (max(0, i-U)<=j <= i-L)就可以得到一个最小值,这样扫描完就得到了答案。

在寻找区间[max(0, i-U), i-L]的最大值的过程其实就是RMQ的过程,可以通过线段树来解决。

#include <cstdio>
#include <cstdlib>

#define MAX  32770
#define max(a, b)(a > b ? a : b)

int preSum[MAX];//对前缀和建立线段树
struct Node
{
	int left, right, mPSum;
}tNode[4*MAX];

void build(int left, int right, int root)
{
	tNode[root].left = left, tNode[root].right = right;
	if(left == right)
	{
		tNode[root].mPSum = preSum[left];
		return;
	}
	int mid = (left+right)>>1;
	build(left, mid, root<<1);
	build(mid+1, right, (root<<1) | 1);
	tNode[root].mPSum = max(tNode[root<<1].mPSum, tNode[(root<<1)|1].mPSum);
}

int query(int left, int right, int root)
{
	if(tNode[root].left == left && tNode[root].right == right)
		return tNode[root].mPSum;
	int mid = (tNode[root].left + tNode[root].right)>>1;
	if(right <= mid)
		return query(left, right, root<<1);
	else if(left > mid)
		return query(left, right, (root<<1) | 1);
	else
		return max(query(left, mid, root<<1), query(mid+1, right, (root<<1) | 1));
}

int main()
{
	int n, L, U, val;
	while(scanf("%d", &n), n)
	{
		scanf("%d %d", &L, &U);
		preSum[0] = 0;
		for(int i=1; i<=n; i++)
		{
			scanf("%d", &val);
			preSum[i] = val + preSum[i-1];
		}
		build(0, n, 1);
		int ans = INT_MAX;
		for(int i=L; i<=n; i++)
		{
			int tmp = query(max(0, i-U), i-L, 1);
			if(preSum[i] - tmp < ans)//更新最小值
				ans = preSum[i] - tmp;
		}
		printf("%d\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值