洛谷P5097 [USACO04OPEN]Cave Cows 2(ST表)
阿新 • • 發佈:2020-11-17
題目
https://www.luogu.com.cn/problem/P5097
思路
簡單的靜態區間最值,開一個ST表就可以搞定(更熟悉線段樹的同學比如我可以用線段樹寫),但ST表碼量更小且常數小。
ST表利用了倍增的思想,就是維護以i位置開頭的,長度為\(2^k\)的區間段中的最值,記為ST[i][k],易得,ST[i][k]=min(ST[i][k-1],ST[i+\(2^{k-1}\)][k-1])。
查詢l,r的區間最小值,就是找到一個最大的k,使\(2^k\leq\) r-l+1。
然後
可能會重疊,但是不要緊,重疊不影響最值。
由於太久沒寫,我程式碼裡的ST[i][k]指的是以[i]結尾的區間資訊QwQ。可能會麻煩一點。
程式碼
#include<cstdio> #include<cstdlib> #include<algorithm> #define maxn 30000 using namespace std; int a[maxn],st[maxn][16]; int log_2[maxn]; int main(){ int n,q,i,j,x,y,ans; scanf("%d%d",&n,&q); for(i=2;i<=n;++i) log_2[i]=log_2[i>>1]+1; for(i=1;i<=n;++i) scanf("%d",&st[i][0]); for(j=1;j<=log_2[n];j++){ for(i=1;i<=n;++i){ if(i>=(1<<j-1)) st[i][j]=min(st[i][j-1],st[i-(1<<j-1)][j-1]); } } for(i=1;i<=q;++i){ scanf("%d%d",&x,&y); int k=log_2[y-x+1]; ans=min(st[y][k],st[x-1+(1<<k)][k]); printf("%d\n",ans); } // system("pause"); return 0; }