[Ybt Advanced 4-3-1] [luogu P3865] Sequence interval / [Template] ST table

Sequence interval

Topic link: ybt high-efficiency advanced 4-3-1 / luogu P3865

General idea

Give you a sequence of numbers, ask multiple times, each time asking for the maximum value in an interval.

Ideas

The first reaction to this question is the line segment tree, but the constant is too large to pass.

We consider using something called the ST table, which mainly uses the idea of ​​doubling the DP to find the maximum value of an interval.
Then because this kind of RMQ (seeking the most value) problem can be compared to the best answer with a number in it multiple times, we use this property to do it.

First, we define fi, j f_{i,j}fi,jCurrency and [i, i + 2 j - 1] [i, i + 2 ^ j-1][i,i+2j1 ] The maximum value of this interval.
It is easy to get the transfer method: (actually the idea of ​​multiplication)
fi, j = max ⁡ {fi, j − 1, fi + 2 j − 1, j − 1} f_{i,j}=\max\{f_ {i,j-1},f_{i+2^{j-1},j-1}\}fi,j=max{ fi,j1,fi+2j - 1 ,j-1}
当然, f i , 0 = a i f_{i,0}=a_i fi,0=ai

Then you consider how to query the maximum value of an interval.
Then we can know that because we are only seeking the maximum value, we can choose some of the known intervals to have coverage, but they must be combined to include all the points you want, and there can be no more.

Then you consider choosing the longest but not exceeding interval from the left, and the longest but not exceeding interval as the end point on the right.
Then you consider that you can directly get the length as 2 x 2^x2The maximum value of each interval of x , then you find the largestxxx ,log isused⁡ \loglo g , because it needs to be used many times, we consider direct linear preprocessing to findlog ⁡ \loglo g (Anyway, only use1 ∼ n 1\sim n1n ).
Then you consider whether this can cover all of them. It is easy to think that both of them are more than half of the length. Putting them on both sides will definitely cover all points.

That's fine, ask every time [l, r] [l,r][l,r ] first findsize = log ⁡ (r − l + 1) size=\log(r-l+1)size=log(rl+1 ) , and the answer ismax ⁡ {fl, size, fr − 2 size + 1, size} \max\{f_{l,size},f_{r-2^{size}+1,size}\}max{ fl,size,fr2size+1,size}

Code

#include<cstdio>
#include<iostream>

using namespace std;

int n, m, a[100001], x, y;
int log[100001], f[100001][17];

void get_log() {
    
    //预处理出 log
	int now = 2, i, noww = 2;
	for (i = 1; noww * 2 <= 100000; i++) {
    
    
		while (now < noww * 2) {
    
    
			log[now] = i;
			now++;
		}
		noww <<= 1;
	}
	while (now <= 100000) {
    
    
		log[now] = i;
		now++;
	}
}

int main() {
    
    
	get_log();
	
	scanf("%d %d", &n, &m);
	
	for (int i = 1; i <= n; i++) {
    
    
		scanf("%d", &a[i]);
		f[i][0] = a[i];
	}
	
	for (int i = 1; i <= log[n]; i++)//构建 ST 表
		for (int j = 1; j <= n; j++)
			if (j + (1 << (i - 1)) > n) f[j][i] = f[j][i - 1];
				else f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);
	
	for (int i = 1; i <= m; i++) {
    
    
		scanf("%d %d", &x, &y);
		int size = log[y - x + 1];//询问
		printf("%d\n", max(f[x][size], f[y - (1 << size) + 1][size]));
	}
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/114992105