线段树之一

#include <iostream>            //poj 3264 线段树,求区间的最值问题
using namespace std;
struct segment
{
int max,min;
}table[
200000];
int arr[50005],MAX,MIN;
void built_tree(int s,int t,int n)
{
if(s==t)
table[n].max
=table[n].min=arr[s];
else
{
int mid=(s+t)/2;
built_tree(s,mid,
2*n);
built_tree(mid
+1,t,2*n+1);
table[n].max
=max(table[2*n].max,table[2*n+1].max);
table[n].min
=min(table[2*n].min,table[2*n+1].min);
}
}
void range(int s,int t,int n,int head,int end)
{
if(s==head&&t==end)
{
MAX
=max(MAX,table[n].max);
MIN
=min(MIN,table[n].min);
}
else
{
int mid=(head+end)/2; //注意不要写成 int mid=(s+t)/2;
if(s<=mid)
range(s,min(mid,t),
2*n,head,mid);
if(t>mid)
range(max(s,mid
+1),t,2*n+1,mid+1,end);
//这里不用也不能再添加 MAX=max(table[2*n].max,table[2*n+1].max); MIN=min(table[2*n].min,table[2*n+1].min);
//因为执行range(s,min(mid,t),2*n,head,mid);之后,MAX已经是MAX=max(MAX,table[2*n].max);
//同理再执行range(max(s,mid+1),t,2*n+1,mid+1,end); MAX已经是table[2*n].max,table[2*n+1].max 两者的最大值了
}
}
int main()
{
int n,q,s,t;
scanf(
"%d%d",&n,&q);
for(int i=1;i<=n;++i) //下标从1开始
scanf("%d",arr+i);
built_tree(
1,n,1);
while(q--)
{
scanf(
"%d%d",&s,&t);
MAX
=0;MIN=1000001;
range(s,t,
1,1,n);
printf(
"%d\n",MAX-MIN);
}
return 0;
}

  

//sicily 1800. Sequence

#include
<iostream> //线段树
#include<cstdio>
using namespace std;
int sum[50000];
struct segment
{
int m;
}table[
200000];
void build(int s,int t,int n)
{
if(s==t)
table[n].m
=sum[s];
else
{
int mid=(s+t)/2;
build(s,mid,
2*n);
build(mid
+1,t,2*n+1);
table[n].m
=max(table[2*n].m,table[2*n+1].m);
}
}
int MAX;
void range(int s,int t,int n,int head,int end)
{
if(s==head&&t==end)
{
MAX
=max(MAX,table[n].m);
}
else
{
int mid=(head+end)/2;
if(s<=mid)
range(s,min(mid,t),
2*n,head,mid);
if(t>mid)
range(max(s,mid
+1),t,2*n+1,mid+1,end);
}
}
int main()
{
int n,num,L,U;
while(cin>>n&&n)
{
scanf(
"%d%d",&L,&U);
for(int i=1;i<=n;++i)
{
scanf(
"%d",&num);
sum[i]
=sum[i-1]+num;
}
build(
1,n,1);
int s=sum[L];
for(int i=L+1;i<=n;++i) //求出以i为结尾,长度从L到U的连续和的最小值,若直接比较,则需要O(n^2)时间,用线段树加以优化,可以达到O(nlogn)
{
MAX
=0x80000000;
range(max(
1,i-U),i-L,1,1,n); //用O(logn)找出sum[i-U]-sum[i-L]中的最大值,使得sum[i]-MAX 为最小值
if(i<=U)
MAX
=max(MAX,0); //需要特别注意该判断语句,如果i<=U,那要考虑覆盖范围从1到i的整个区间,此时应是sum[i]-0
s=min(s,sum[i]-MAX);
}
printf(
"%d\n",s);
}
return 0;
}

  

posted on 2011-07-17 01:55  sysu_mjc  阅读(156)  评论(0编辑  收藏  举报

导航