• RMQ-ST表 专题训练


    ST表简介

    ST表示解决RMQ问题的一种暴力手段,处理时间(O(nlog_{2}{n})),查询时间(O(1)),空间(O(nlog_{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
    ",max(dp[x][k],dp[y-(1<<k)+1][k]));
    	}
    	return 0;
    }
    
  • 相关阅读:
    搜狗拼音输入法候选框有时会跑到屏幕的左上角
    力扣 94. 二叉树的中序遍历
    让我们了解 Ceph 分布式存储
    HDFS的架构和设计要点
    业级PPTP服务器搭建企
    FastCGI中fastcgi_param 详细说明
    LAMP两种模式
    CentOS 7.4搭建LAMP,LAMP:Linux、Apache、MySQL、PHP
    centos7 7.3php编译安装
    Linux下编译安装MariaDB
  • 原文地址:https://www.cnblogs.com/tldr/p/11261351.html
Copyright © 2020-2023  润新知