st表介绍
st表图示
st表用了倍增的原理,可以解决区间最值问题(RMQ问题)
先预处理出所有长度为2的1至log2(n)次方的区间,可以用递归来求。
定义st[i][j]为起点为i,长度为
2
j
2^j
2j的区间内的最大值、最小值。
计算st[i][j]时,可以把区间拆成两部分,前半部分、和后半部分,都长度为
2
j
−
1
2^{j-1}
2j−1,前半部分的起点很显然是i,后半部分的起点(前半部分的起点+前半部分的长度),所以后半部分的起点是(i+(1<<(j-1))),可以得到公式st[i][j]=max/min(st[i][j-1],st[i+(1<<(j-1))])
练练手
P3865 【模板】ST 表 && RMQ 问题
此题甚水,直接上代码
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int n,m,dp[100005][30],lg[100005];
int main()
{
n = read();
m = read();
for(int i = 1;i <= n;i ++)dp[i][0] = read();
for(int i = 2;i <= n;i ++)lg[i] = lg[i / 2] + 1;
for(int j = 1;j <= lg[n];j ++)
{
for(int i = 1;i <= n - (1 << j) + 1;i ++)
{
dp[i][j] = max(dp[i][j - 1],dp[i + (1 << (j - 1))][j - 1]);
}
}
for(int i = 1;i <= m;i ++)
{
int l,r,len;
l = read();
r = read();
len = lg[r - l + 1];
cout << max(dp[l][len],dp[r - (1 << len) + 1][len]) << '\n';
}
return 0;
}
P1198 [JSOI2008] 最大数
这道题其实就是多了一个插入操作
就是每次会计算一遍以新来的结尾的答案
完整代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int id,x;
};
int m,d,len,t,k;
long long n;
char op;
vector<node>v;
int main()
{
cin>>m>>d;
for( int i=1;i<=m;i++)
{
cin>>op;
if(op=='Q')
{
cin>>len;
int l=0,r=v.size()-1;
while(l<r)
{
int mid=(l+r)>>1;
if(v[mid].id<k-len+1)
{
l=mid+1;
}
else
{
r=mid;
}
}
cout<<v[l].x<<'\n';
t=v[l].x;
}
else if(op=='A')
{
cin>>n;
n+=t;
n%=d;
while(v.size()>0&&v.back().x<=n)v.pop_back();
k++;
v.push_back({k,n});
}
}
return 0;
}