您的位置:首页 > 产品设计 > UI/UE

Sicily 1800 Sequence(RMQ)

2010-07-25 11:29 399 查看
//RMQ(线段树求解)
//A这道题后,懂得了对数列的转换,如果要求连续区间和,就必须把它转化成SUM[I],表示从1到I的区间之和
//这样的话要求任意区间的和,假设[I,J]的和,只需要sum[j] - sum[i-1]就可以立即求出来了
//注意sum[0] = 0;
//思路:枚举从L开始到的的sum[i](i >= L)
//对符合长度条件的区间中找到一个最大的sum[j]  (max(0,i-U) <= j <= i-L)
//这样的话sum[i] - sum[j]便是最小的
//这样就将问题转化为求给定区间的最大值
//这道题不能用ST算法来做,用ST会超时,可能是在log的运算那里花去太多时间
//看了别人的题解,看到有用优先队列优化的,这个的速度应该更快
#include<iostream>
#define MAX 32780
#define INF 2147483647
using namespace std;
int n,L,U;
int sum[MAX];
int _max,ans;
struct seg
{
int l,r,_max;
}segTree[MAX * 4];
void buildTree(int fa,int l,int r)
{
segTree[fa].l = l;
segTree[fa].r = r;
if(l == r)
{
segTree[fa]._max = sum[l];
return;
}
int mid = (l + r) >> 1;
buildTree(2*fa,l,mid);
buildTree(2*fa+1,mid+1,r);
segTree[fa]._max = max(segTree[2*fa]._max,segTree[2*fa+1]._max);
}
void search(int fa,int l,int r)
{
if(segTree[fa].l == l && segTree[fa].r == r)
{
_max = max(_max,segTree[fa]._max);
return;
}
int mid = (segTree[fa].l + segTree[fa].r) >> 1;
if(r <= mid)	search(2*fa,l,r);
else if(l > mid)	search(2*fa+1,l,r);
else
{
search(2*fa,l,mid);
search(2*fa+1,mid+1,r);
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n) && n)
{
ans = INF;
scanf("%d%d",&L,&U);
sum[0] = 0;
for(int i = 1;i <= n;++i)
{
scanf("%d",∑[i]);
sum[i] += sum[i-1];
}
buildTree(1,0,n);
for(int i = L;i <= n;++i)
{
_max = (-1)*INF;
search(1,max(0,i - U),i - L);
if(sum[i] - _max < ans)
ans = sum[i] - _max;
}
printf("%d/n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: