倍増
これは乗算であり、毎回2を乗算するのと同じであることが理解しやすいため、乗算は通常、バイナリビット演算に関連付けることができます。掛け算法の特徴は、1、2、4 、…、2 k 1、2、4、…、2 ^ kを事前に計算する必要があることです。1 、2 、4 、…、2Kスプリングボード、これにはデータが静的で動的ではないことが必要です。データが変更された場合、すべてのスプリングボードを再計算する必要があり、スプリングボードは無意味です。
乗算法の古典的なアプリケーションは、行列高速電力、接尾辞配列、STアルゴリズム、LCA(最も近い共通の祖先)です。このセクションでは、比較的単純なSTアルゴリズムを紹介し、乗算を適用するという古典的な問題も示します。
STアルゴリズム
STアルゴリズムは、主に静的RMQ問題、つまり、値を変更せずに最大および最小アクセス間隔を解決します。主なアイデアは、広い領域で最良の値を見つけ、小さな領域を大きな領域にマージすることです。結果は、分離された領域の中で最良の値になり、結果を見つけます。たとえば、少し複雑です。
要求1-20,那么我们可以分解成 min(或max)(dp[1][16],dp[17][20]);
能分解成min(或max)(dp[1][16],dp[17][20]); 这样当然也就是可以分解成这样:
min(或max)(dp[1][16],dp[20-16+1][20]);
就是有重复的,因为我们要求的最值所以重复不会影响结果。
dp[i][j]表示i到j存的最小/大值。
为什么是16那?不可以是10,14,15吗?
当然可以只不过用16会更优化 因为16是2的倍数,那么我们就可以引入倍增了。
ST思想:
(1)把整个数列分为很多小区间,并提前计算出每个小区间的最值;
(2)对任意一个区间最值查询,找到覆盖它的两个小区间,用两个小区间的最值算出答案。
羅さんの写真を使うのはいいことですが、もちろん羅さんの方が上手く書いています。
まず、間隔に格納されている最大値であるST配列を最初に作成します。間隔の長さは最大値の1です。前に、乗算は踏み台として機能すると述べたので、2 0 2 ^ 0から開始できます。20ジャンプして21 2 ^ 121(つまり、動的計画法の考え方を使用して、21は2つに均等に分割されます)これは、2 1 2 ^ 1の間隔の長さです21の最大値。これにより、2 2 2 ^ 2にジャンプできます。22
…
ジャンプできなくなるまで(1 << k)>ジャンプできなくなるまで、元の配列の長さより長くなります。
したがって、再帰式を見つけることができます。
dp[l][k]=max(dp[l][ k - 1],dp[ r - 1<<( k - 1) + 1][ k - 1 ]);
長さは1 <<(k − 1)1 <<(k-1)1<<(k−1 )終点はrrですrの開始点はr-1 <<(k-r−1<<(k−1 )+1
lllは左のエンドポイント、kkですkは、2進数の数、つまり長さ(2のk乗)です。rrrは正しいエンドポイントです。
P2880USACO07JANBバランスラインナップG
別の日を説明する
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
ll n,m;
ll d[50010][100],p[50001][100];
ll a[maxn],b[100];
int main() {
scanf("%lld%lld",&n,&m);
for(int i=1; i<=n; i++)scanf("%lld",&a[i]),d[i][0]=p[i][0]=a[i];
b[0]=1;
ll flag=0;
for(int i=1; i<64; i++) {
b[i]=b[i-1]*2;
if(b[i]>=n) {
flag=i;
break;
}
}
for(int i=1; i<=flag; i++) {
for(int j=1;j<=n-b[i]+1;j++){
d[j][i]=min(d[j][i-1],d[j+b[i-1]][i-1]);
p[j][i]=max(p[j][i-1],p[j+b[i-1]][i-1]);
}
}
while(m--) {
ll l,r;
scanf("%lld%lld",&l,&r);
ll len=r-l+1;
ll k;
for(int i=0;i<=flag;i++){
if(b[i]<=len){
k=i;
}else break;
}
ll minn=min(d[l][k],d[r-b[k]+1][k]);
ll maxx=max(p[l][k],p[r-b[k]+1][k]);
printf("%lld\n",maxx-minn);
}
return 0;
}