【ST表】

【ST表】

用于解决区间最值问题(RMQ)
涉及到许多查询区间最小值/最大值问题时->用ST表维护

预处理操作 O(nlogn)
查询操作 O(1)
思想:动态规划+倍增

ST表构建思路

(1)区间dp:dp[l][r]=max(dp[l][x],dp[x+1][r])
(2)二进制优化:对于每个区间长度 都可以分解为2的幂次方之和
(3)空间优化:倍增优化
image
image
image
image

模版代码

https://www.luogu.com.cn/problem/P3865

struct ST{
    vector<vector<int> > f;
    vector<int> lg;//预处理取对数向下取整
    ST(int n):f(n+1,vector<int>(64)),lg(n+1){
        lg[1]=0;
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++) f[i][0]=a[i];
        for (int j=1;j<=lg[n];j++)
	        for (int i=1;i<=n-(1<<j)+1;i++){
		        f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
				//同理,查区间最小值就改成min
	    }
    }
    int ask(int x,int y){
		int l=lg[y-x+1];
		return max(f[x][l],f[y-(1<<l)+1][l]);
    }
};

【题目整理】

一起走很长的路!

https://ac.nowcoder.com/acm/contest/95334/E

/*【思路】
本质上是求l到i-1的区间和大于a[i]
转换为前缀和形式:sum[i-1]-sum[l-1]>=a[i]
合并同类项:sum[i-1]-a[i]>=sum[l-1]
->设d[i]=sum[i-1]-a[i]
求d[i]最小值:
如果>=sum[l-1]则完美
如果<sum[l-1] 则答案为sum[l-1]-d[i]最小值
*/
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int,int> PII;
const int N=200010;
int n,q;
int a[N],s[N],d[N];//注意前缀和的题目:a在1e9的情况下记得开longlong
struct ST{
    vector<vector<int> > f;
    vector<int> lg;//预处理取对数向下取整
    ST(int n):f(n+1,vector<int>(64)),lg(n+1){
        lg[1]=0;
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++) f[i][0]=d[i];
        for (int j=1;j<=lg[n];j++)
	        for (int i=1;i<=n-(1<<j)+1;i++){
		        f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
				//同理,查区间最小值就改成min
	    }
    }
    int ask(int x,int y){
		int l=lg[y-x+1];
		return min(f[x][l],f[y-(1<<l)+1][l]);
    }
};
signed main(){
      ios::sync_with_stdio(0);
      cin.tie(0);
      cout.tie(0);
      cin>>n>>q;
      for(int i=1;i<=n;i++){
            cin>>a[i];
            s[i]=s[i-1]+a[i];
      }
      for(int i=1;i<=n;i++) d[i]=s[i-1]-a[i];
      ST st(n);
      while(q--){
            int l,r;
            cin>>l>>r;
            if(l==r){//记得特判
                  cout<<"0"<<endl;
                  continue;
            }
            int cnt=st.ask(l+1,r)-s[l-1];
            if(cnt<0) cout<<-cnt<<endl;
            else cout<<"0"<<endl;
      }
      return 0;
}
posted @ 2025-01-25 14:28  White_ink  阅读(20)  评论(0)    收藏  举报