至今没有实现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.