• 浅谈 倍增/ST表


    命题描述

    给定一个长度为 (n) 的序列,(m) 次询问区间最大值

    分析

    上面的问题肯定可以暴力对吧。
    但暴力肯定不是最优对吧,所以我们直接就不考虑了。。。

    于是引入:倍增

    首先,倍增是个什么东西?

    在这里转一篇写的超棒的blog,点我。要是这都没看懂你就连小白兔都不如我就无语了。

    总的来说,其实就是倒着运用二分的思想,从需求小的慢慢倍增把答案更新到需求大的

    ST表就是一种常见的倍增思想的运用

    关于ST表

    ST表和树状数组,线段树这两种算法一样,是一种用于解决 (RMQ(Range Minimum/Maximum Query))多次区间查询问题的离线算法

    ST表的主要思想是构建一个二维数组 (st[i][j]),这个二维数组表示需要查询的数组的从下标 (i) 到下标 (i + 2^{j - 1}) 的最值,这里以最大值为例。超像 (dp) 的说~

    我们可以把 ([i, j]) 拆成数量相等的两半,在求出这两部分的最大值即可,故:

    st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1];
    

    再枚举一下 (i, j) 就可以了。点儿都不高级


    接下来,该怎么实现查询呢?

    如果查询的区间长度刚好是 (2^k(k为整数)),直接输出 (st[l][log(r - l + 1) / log(2)]) 即可;

    如果不是,也很简单,我们还是将所给区间分为两部分。
    首先规定在 (st[i][j])(i = l)(j = k),区间长度 (len = r - l + 1)
    会发现最大的(k) 应满足 (2^k <= len) (这样以 (l) 开头的ST表数据覆盖需要查询的区间中的数最多)

    所以 (k = (int) (log(len)/log(2)))
    显然查询时的区间 ([l,r]) 分成的右边部分的左端点 (x = r + 1 - 2^p)

    具体实现
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 100005;
    int st[MAXN][41];
    
    void read(int &a) { // 读优
    	int k = 1;
    	a = 0;
    	char s = getchar();
    	while(s < '0' || s > '9') {
    		if(s == '-') k = -1;
    		s = getchar();
    	}
    	while(s >= '0' && s <= '9') { 
    		a = a * 10 + (s - '0');
    		s = getchar();
    	} 
    	a *= k;
    }
    
    int main() {
    	int n, m;
    	read(n); read(m);
    	for(int i = 1; i <= n; i++) read(st[i][0]);
    	
    	for(int j = 1; j <= (int)(log(n) / log(2)); j++)
    		for(int i = 1; i + (1 << j) - 1 <= n; i++)
    			st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
    			
    	for(int i = 1; i <= m; i++) {
    		int l, r;
    		read(l); read(r);
    		int k = (int)(log(r - l + 1) / log(2));
                    printf("%d
    ", max(st[l][k], st[r - (1 << k) + 1][k]));
    	}
    	return 0;
    }
    

  • 相关阅读:
    POJ 2253 Frogger
    C++map函数的用法
    蓝桥杯 幂方分解
    蓝桥杯 危险系数
    POJ 2234 Matches Game
    POJ 1852 Ants
    POJ 1144 Network
    POJ1419 Graph Coloring
    poj 2573 Bridge(有A、B、C、D四个人,要在夜里过一座桥……)
    小知识(输出源文件的标题和目前执行行的行数)
  • 原文地址:https://www.cnblogs.com/Chain-Forward-Star/p/13868234.html
Copyright © 2020-2023  润新知