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.









你可能感兴趣的:(树状数组)