您的位置:首页 > 其它

Uva 6609 - Minimal Subarray Length(RMQ)

2017-08-01 19:42 441 查看
题目地址https://cn.vjudge.net/problem/UVALive-6609(排版问题,不能摘抄到博客)。

自从知道了RMQ算法,一直想找题试试水, 今天正好碰到组队赛的一题用上了。

题目大意就是给你个长度为n的数字序列,让你找出之中连续子序列的加和大于等于x的最小长度。虽然有更快的方法,但就当那RMQ练练手了。

大体思路:RMQ预处理后枚举i, 找到满足sum[j] - sum[i] >= x 的(j - i)最小值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
#define N 501000
#define log2(x) log(x) / log(2)
using namespace std;
void RMQ(int n);//RMQ预处理
long long int sum
[25];
int Question(int, int );//询问函数
int main()
{
int n, t, x;

cin >> t;
while(t--)
{
scanf("%d%d", &n, &x);
sum[0][0] = 0;
for(int i = 1; i <= n; i++)
{
int m;
scanf("%d", &m);
sum[i][0] = sum[i - 1][0] + m;
}
RMQ(n);
int ans = N;
for(int i = 0; i < n; i++)//枚举i
{
int l = i + 1;
int r = n;
int mid;
while(r > l)//二分查找满足sum[j] - sum[i] >=x 的 j - i的最小值。
{
mid = (r + l) / 2;
if(Question(i + 1, mid) - sum[i][0] >= x)
{
r = mid;
}
else
{
l = mid + 1;
}

}
if(sum[r][0] - sum[i][0] >= x)
{
ans = min(ans, r - i);
}
}
if(ans == N)
{
ans = -1;
}
printf("%d\n", ans);

}
}
void RMQ(int num)//RMQ预处理
{
for(int j = 1; j <= 20; j++)
{
for(int i = 1; i <= num; i++)
{
if(i + (1 << j) - 1 <= num)
{
sum[i][j] = max(sum[i][j - 1], sum[i + (1 << (j - 1))][j - 1]);
}
else
break;
}
}
}
int Question(int i, int j)
{
int k = log2(j - i + 1);
return max(sum[i][k], sum[j - (1 << k) + 1][k]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 RMQ