标签:st表 维护 简介 如何 一个 efi long false inf
ST表示解决RMQ问题的一种暴力手段,处理时间\(O(n\log_{2}{n})\),查询时间\(O(1)\),空间\(O(n\log_{2}{n})\).
ST表的第0列存放第一层数据,即原始数据;
ST表的第1列存放第二层数据,即步长为\(2^0\)的\(min/max\)的数据;
ST表的第2列存放步长为\(2^1\)的\(min/max\)的数据;
...
以此类推可以看出什么呢?
每一列维护的范围是上一列的2倍,类似树状数组。也就是说,第一列维护自己,第二列维护\([i,i+1]\),第三列维护\([i,i+3]\)...
到第\(\log_{2}{n}\)列时,维护所有的数据。
如何查询呢?
假设查询\([x,y]\)区间内的\(min/max\),则我们需要查询的是层数是\(k=\log_{2}{y-x+1}\)
有一个定理:$ 2^{\log_{2}{diff}}>diff/2 $,因为 $n/2 < \log_{x}{diff}<=n,(2^n=diff) $,因此此时第k层的步长为\(2^{k}>(y-x+1)/2\)正好大于需要查询区间的一半以上
而第k层的\(x\)行维护了\([x,x+2^k-1]\)的数据,\(y-2^k+1\)行维护了\([y-2^k+1,y]\)的区间,两者有重复,但是合起来正好覆盖\([x,y]\)的区域
只要取\(max([x][k],[y-2^k+1][k])\)即可完成。
经典题:
洛谷 P1816忠诚
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
#define INF 0x3f3f3f3f;
#define MAXN 1000100
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int n,m,arr[MAXN],dp[MAXN][60],x,y;
int main()
{
cin>>n>>m;
FOR2(i,1,n)cin>>arr[i],dp[i][0]=arr[i];
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);//步长为1<<j-1
}
}
while(m--)
{
scanf("%d%d",&x,&y);
int k=log2(y-x+1);//求第几阶
cout<<min(dp[x][k],dp[y-(1<<k)+1][k])<<" ";
}
return 0;
}
洛谷 P2880平衡的阵容
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
#define INF 0x3f3f3f3f;
#define MAXN 1000100
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int x,y,n,m,arr[MAXN],dpmax[MAXN][60],dpmin[MAXN][60];
int main()
{
cin>>n>>m;
FOR2(i,1,n)cin>>arr[i],dpmax[i][0]=dpmin[i][0]=arr[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
{
dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<j-1)][j-1]);
dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<j-1)][j-1]);
}
while(m--)
{
cin>>x>>y;
int k=log2(y-x+1);
cout<<max(dpmax[x][k],dpmax[y-(1<<k)+1][k])-min(dpmin[x][k],dpmin[y-(1<<k)+1][k])<<endl;;
}
return 0;
}
洛谷 P3865模板ST表
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
#define INF 0x3f3f3f3f;
#define MAXN 1000100
#define MOD 10007
#define sf(a,b) read(a),read(b)
using namespace std;
int n,m,arr[MAXN],dp[MAXN][60],x,y;
int main()
{
cin>>n>>m;
FOR2(i,1,n)
{
scanf("%d",&arr[i]);
dp[i][0]=arr[i];
}
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);//步进
}
}
// for(int i=0;i<=n;i++)
// {
// for(int j=0;j<10;j++)
// {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
while(m--)
{
scanf("%d%d",&x,&y);
int k=log2(y-x+1);//还原
printf("%d\n",max(dp[x][k],dp[y-(1<<k)+1][k]));
}
return 0;
}
标签:st表 维护 简介 如何 一个 efi long false inf
原文地址:https://www.cnblogs.com/tldr/p/11261351.html