范围最小值问题,利用进行预处理可以做到nlogn的处理和1的查询。
#include<cstdio> #include<cstring> #include<iostream> #include<stack> #include<map> #include<vector> #include<queue> #include<set> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXD (1 << 10) #define MAX_SIZE 1000 + 10 int d[MAXD][MAXD]; void RMQ_init(const vector<int>&A){ int n = A.size(); for(int i = 0 ; i < n ; i++) d[i][0] = A[i]; for(int j = 1 ; (1 << j) < n ; j++) for(int i = 0 ; i + (1 << j ) - 1 < n ; i++){ d[i][j] = min(d[i][j - 1],d[i + (1 << (j- 1))][j - 1]); } } int RMQ(int L,int R){ int k = 0; while((1 << (k + 1)) <= (R - L + 1)) k++; return min(d[L][k],d[R - (1 << k) + 1][k]); } int main(){ int n; vector<int>arr; scanf("%d",&n); for(int i = 0 ; i < n ; i++){ int t; scanf("%d",&t); arr.push_back(t); } RMQ_init(arr); int l,r; while(scanf("%d%d",&l,&r) != EOF){ int ans = RMQ(l,r); printf("The min number in (%d,%d) is %d\n",l,r,ans); } }利用线段树实现RQM,可以做到一遍查询一遍进行改点。
查询说白了就是顺着结点不断往下分区间,当当前的区间被包含在[ql,q2](所求最小值的所在区间)的时候,进行return。
插入的时候更简单了,将A[p] = v,那么不断的往下分区间,知道区间 L = R (也就是 L = R = p)的时候return
#include <vector> #include <list> #include <map> #include <string> #include <set> #include <cstring> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define maxd 1 << 10 #define INF 1 << 30 int minv[maxd]; int v,p; int ql,qr; /*查询[ql,qr]区间内的最小值*/ int query(int o,int L,int R){ int M = L + (R - L) / 2,ans = INF; if(ql <= L && R <= qr) return minv[o]; else if(ql <= M) ans = min(ans,query(o * 2 , L ,M)); else if(M < qr) ans = min(ans,query(o * 2 + 1,M + 1, R)); return ans; } void update(int o,int L,int R){ /*我们修改A[p] = v,o代表当前的结点,L,R代表当前结点的区间范围*/ int M = L + (R - L)/2; if(L == R) minv[o] = v; else{ if(p <= M) /*如果这个点在左子树区间*/ update(o * 2,L,M); else update(o * 2 + 1,M + 1,R); minv[o] = min(minv[o * 2],minv[o * 2 + 1]); } } int main(){ int n,m; scanf("%d",&n); for(int i = 0 ; i < n ; i++){ p = i + 1; scanf("%d",&v); update(1,1,n); } char str[10]; while(scanf("%s",str) != EOF){ if(str[0] == 'A'){ scanf("%d%d",&p,&v); update(1,0,n); } else { scanf("%d%d",&ql,&qr); int ans = query(1,1,n); printf("%d\n",ans); } } return 0; }