---------------------------------------------------------------------------------
pre[len][L]表示左边界为L,长度为Len的区间中的最小值;
那么对于一个询问[L,R],我只要找到小于这个区间长度的最大的2的非负整数次幂(T),那么这个区间中的最小值就是min{pre[T][L],pre[T][R-T+1]}
一直tle,把cin改成scanf后ac了,==。
#include <set> #include <map> #include <stack> #include <queue> #include <cmath> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define MAX(a,b) ((a)>=(b)?(a):(b)) #define MIN(a,b) ((a)<=(b)?(a):(b)) #define OO 0x0fffffff using namespace std; typedef long long LL; const int N = 1000100; int pre[32][N]; int pow2[32]; int get(int data){ if(!data) return 0; int ret = 0; while(data){ data>>=1; ret++; } return ret-1; } int main(){ for(int i=0;i<32;i++) pow2[i]=(1<<i); int n; cin>>n; for(int i=0;i<n;i++) scanf("%d",&pre[0][i]); int maxLen = get(n); for(int len=1;len<=maxLen;len++) for(int i=0;i+pow2[len]<=n;i++){ pre[len][i] = MIN(pre[len-1][i],pre[len-1][i+pow2[len-1]]); } int q,a,b,c; cin>>q; while(q--){ scanf("%d%d",&a,&b); a--,b--; c = get(b-a+1); printf("%d ",MIN(pre[c][a],pre[c][b-pow2[c]+1])); } return 0; }