RMQ问题的ST、树状数组和线段树解法

至今没有实现ST、树状数组的修改操作,不过线段树应该足够应付大部分题目了。

树状数组:

#include <stdio.h>
#define MAXN 1000000
int n, m, l, r, i, j;
int idx[MAXN];
int num[MAXN];

int min(int a, int b)
{
    return a < b ? a : b;
}

int lowbit(int x)
{
    return x & -x;
}

void init()
{
    int i, j;
    for (i = 1; i <= m; i++)
    {
        idx[i] = num[i];
        for (j = 1; j < lowbit(i); j <<= 1)
            idx[i] = min(idx[i], idx[i-j]);
    }
}



int query(int l, int r)
{
    int ans = num[r];
    while (1)
    {
        ans = min(ans, num[r]);
        if (r == l) break;
        for (r--; r - l >= lowbit(r); r -= lowbit(r))
            ans = min(ans, idx[r]);
    }
    return ans;
}


int main()
{
    scanf("%d%d", &m, &n);
    for (i = 1; i <= m; i++)
        scanf("%d", &num[i]);
    init();
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d", &l, &r);
        printf("%d ",query(l, r));
    }
    printf("\n");
    return 0;
}

ST算法:

/*
    RMQ问题
    写的时候犯了三个错误:
    1.数学函数用错了
    2.变量、细节出错
    3.运算符优先级农村

    C语言的+-运算符优先级比<<高啊!!!
    P转C的孩纸你伤不起啊!!!
*/

#include <stdio.h>
#include <math.h>
#define MAXN 1000000

int f[MAXN][32];
int m, n;

int min(int a, int b)
{
    return a < b ? a : b;
}

int main()
{
    int i, j , k, left, right;
    scanf("%d%d", &m, &n);
    for (i = 1; i <= m; i++)
        scanf("%d", &f[i][0]);
    for (j = 1; j <= log2(m); j++)
        for (i = 1; i <= (m - (1 << j) + 1); i++)
            f[i][j] = min(f[i][j-1], f[i + (1 << (j-1))][j-1]);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d", &left, &right);
        k = floor(log2(right - left + 1));
        printf("%d ", min(f[left][k], f[right - (1 << k) + 1][k]));
    }
    printf("\n");
    return 0;
}

 

线段树

var
  t,left,right,a:Array[0..1000000] of longint;
  i,j,k,m,n,cmd,x,y:longint;


function min(a,b:longint):longint;
begin
  if a<b then exit(a) else exit(b);
end;

function build(p,l,r:longint):longint;
var
  m:longint;
begin
  left[p]:=l;
  right[p]:=r;
  if l=r then
    t[p]:=a[l]
  else begin
    m:=(l+r) div 2;
    t[p]:=min( build(p*2,l,m),
           build(p*2+1,m+1,r));
  end;
  exit(t[p]);
end;

function query(p,l,r:longint):longint;
var
  m:longint;
begin
  if (l=left[p])and(r=right[p]) then exit(t[p])
  else begin
    m:=(left[p]+right[p]) shr 1;
    if r<=m then exit(query(p*2,l,r))
    else if l>m then exit(query(p*2+1,l,r))
    else exit(min(query(p*2,l,m),query(p*2+1,m+1,r)));
  end;
end;

procedure change(p,x,y:longint);
var
  m:longint;
begin
  if left[p]=right[p] then
  begin
    t[p]:=y;
    exit;
  end;
  m:=(left[p]+right[p]) shr 1;
  if x<=m then
    change(p*2,x,y)
  else change(p*2+1,x,y);
  t[p]:=min(t[p*2],t[p*2+1]);
end;



begin
  readln(n,k);
  for i:=1 to n do
    read(a[i]);
  fillchar(t,sizeof(t),127);
  build(1,1,n);
  for i:=1 to k-1 do
  begin
    readln(cmd,x,y);
    if cmd=1 then write(query(1,x,y),' ')
    else change(1,x,y);
  end;
  readln(cmd,x,y);
  if cmd=1 then writeln(query(1,x,y),' ')
  else change(1,x,y);
end.




posted on 2011-07-14 08:13  oa414  阅读(353)  评论(1编辑  收藏  举报

导航