您的位置:首页 > 其它

POJ 3264 Balanced Lineup【RMQ附模板】

2014-07-24 17:46 513 查看
题目:http://poj.org/problem?id=3264

输入n和m组,接着n个数,然后是每组的区间下标范围,求这个区间内的最大与最小的差

参考好多:
http://blog.sina.com.cn/s/blog_9ec86af101013o84.html http://www.cnblogs.com/whatbeg/p/3582486.html http://www.myext.cn/other/a_7364.html http://baike.baidu.com/view/1536346.htm
RMQ 1813MS
O(nlogn)预处理 O(1)应答

dp[i][j]表示从i号元素开始2^j个元素间的最值

dp[i][j-1] 表示[i,i+2^(j-1)-1]

dp[i+(1<<(j-1))][j-1] 表示[i+2^(j-1),i+2^j-1]

ST算法:

#include<iostream>
#include<cmath>
using namespace std;
#define max_(a,b) ((a)>(b)?(a):(b))
#define min_(a,b) ((a)>(b)?(b):(a))
int h[51005];
int maxdp[51001][20],mindp[51001][20];
int n,m;
void Init()
{
int i,j,t;
for(i=1;i<=n;i++)
{
maxdp[i][0] = h[i];
mindp[i][0] = h[i];
}
for(j=1; (1<<j) <=n; j++)
{
for(i=1; i+(1<<j)-1<=n; i++)
{
t = i + (1 << (j-1));	//注意+比<<优先级高
maxdp[i][j] = max_(maxdp[i][j-1],maxdp[t][j-1]);
mindp[i][j] = min_(mindp[i][j-1],mindp[t][j-1]);
}
}
}

int rmq(int l,int r)
{
int k,mx,my;
k=(int)(log(r-l+1.0)/log(2.0));
mx = max_(maxdp[l][k],maxdp[r-(1<<k)+1][k]);
my = min_(mindp[l][k],mindp[r-(1<<k)+1][k]);
return mx-my;
}
int main()
{
int l,r,i;
//	freopen("a.txt","r",stdin);
int rmp(int l,int r);
while(~scanf("%d%d",&n,&m))
{
for( i=1;i<=n;i++) scanf("%d",&h[i]);
Init();
for( i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
printf("%d\n",rmq(l,r));
}
}
return 0;
}


线段树:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define INF 0x7FFFFFFF
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin)
#define WE freopen("1.out","w",stdout)

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))

#define MAX 50001
int ans1,ans2;  //整体的最大最小
int a[MAX];

struct node
{
int l,r;        //i结点的区间范围
int nMax,nMin;  //[l,r]的最值
}tree[MAX*4];
void build(int i,int l,int r)   //在结点i处建立[l,r]的区间
{
tree[i].l = l;
tree[i].r = r;
if(l == r)    //叶结点
{
tree[i].nMax = tree[i].nMin = a[l];
return;
}
int mid = (l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
tree[i].nMax = max(tree[i<<1].nMax,tree[i<<1|1].nMax);
tree[i].nMin = min(tree[i<<1].nMin,tree[i<<1|1].nMin);
}
void query(int i,int l,int r)       //在i号结点查询[l,r]
{
if(tree[i].l == l && tree[i].r == r)    //完全覆盖了
{
ans1 = max(tree[i].nMax,ans1);
ans2 = min(tree[i].nMin,ans2);
return;
}
int mid = (tree[i].l+tree[i].r)>>1;
if(r <= mid)        //被查询的区间被含于i结点左区间,就去左子树找该区间
query(i<<1,l,r);
else if(l > mid)    //右子树找该区间
query(i<<1|1,l,r);
else    //  l<=mid && r>mid [l,r各在一边],[l,mid]在做左子树找
{
query(i<<1,l,mid);
query(i<<1|1,mid+1,r);
}
}

int main()
{
int n,m,l,r;
// RE;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i = 1; i <= n;i++)
scanf("%d",&a[i]);
build(1,1,n);
REP(i,m)
{
scanf("%d%d",&l,&r);
ans1 = -INF;
ans2 = INF;
query(1,l,r);
printf("%d\n",ans1-ans2);
}
}
return 0;
}


ST模板

#include <stdio.h>
#include <math.h>
#define MIN 30
#define MAX 50050
int n,m,arr[MAX];
int maxdp[MAX][MIN],mindp[MAX][MIN];
int RMQ(int x,int y,int flag);

int max_m(int a,int b)
{
return a>b?a:b;
}
int min_m(int a,int b)
{
return a>b?b:a;
}

void Create(int flag)
{				//flag = 0建立最大rmq,flag = 1最小
int i,j,t;
if (flag == 0)
{
for (i = 1; i <= n; ++i)
maxdp[i][0] = arr[i];
for (j = 1; (1<<j) <= n; ++j)
for (i = 1; i+(1<<j)-1 <= n; ++i)
{
t = i + ( 1 << (j-1) );
maxdp[i][j] = max_m(maxdp[i][j-1],maxdp[t][j-1]);
}
}
else
{
for (i = 1; i <= n; ++i)
mindp[i][0] = arr[i];
for (j = 1; (1<<j) <= n; ++j)
for (i = 1; i+(1<<j)-1 <= n; ++i)
{
t = i + ( 1 << (j-1) );
mindp[i][j] = min_m(mindp[i][j-1],mindp[t][j-1]);
}
}
}

int RMQ(int l,int r,int flag)
{				//flag = 0查询最大rmq,flag = 1最小
int k = (int)(log(r-l+1.0)/log(2.0));
if (flag == 0)
return max_m(maxdp[l][k],maxdp[r-(1<<k)+1][k]);
else
return	min_m(mindp[l][k],mindp[r-(1<<k)+1][k]);
}

int main()
{
int i,j,k;
scanf("%d%d",&n,&m);
for (i = 1; i <= n; ++i)
scanf("%d",&arr[i]);

Create(1);
Create(0);
for (i = 1; i <= m; ++i) {
scanf("%d%d",&j,&k);
printf("%d\n",RMQ(j,k,0) - RMQ(j,k,1));
}
}

/*	//若数组从0开始,其他不变
void Init(){
int i,j,t;
for (i = 0; i < n; ++i)
mindp[i][0] =h[ i];
for (j = 1; (1<<j) <= n; ++j){
for (i = 0; i+(1<<j)-1 < n; ++i){
t = i + ( 1 << (j-1) );
mindp[i][j] = min_m(mindp[i][j-1],mindp[t][j-1]);
}
}
}
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: