CSP-S T2 analog campus

beautiful

DESCRIPTION:

A sequence of length n, for each value has a beautiful ai i the number of positions, defined as: find the sequence most
long [l, r], satisfies l <i <r, and [l, r ] median AI (we compare the size of the sequence number of the two positions,
to a first value of a keyword, the keyword index to a second comparison. in this case [l, r] may be the length of only odd ), r - l + 1 is the value of i beautiful.
Then there is a query Q, each interrogation [l, r] represents the maximum value of the query interval [l, r] value beautiful.

INPUT:

The first line of the next n input n integers, representing the next ai Q, Q representatives intervals Next Q lines of
two integers l, r represents the left and right end sections

OUTPUT:

For inquiries each interval, the output answer

SAMPLE INPUT:

8
16 19 7 8 9 11 20 16
8
3 8
1 4
2 3
1 1
5 5
1 2
2 8
7 8

SAMPLE OUTPUT:

7
3
1
3
5
3
7
3

data range:

30%: N, Q <= 50
70%: N, Q <= 2000
100%: N <= 2000, Q <= 100000, AI <= 200 is
for all data, satisfies n <= 2000, Q <= 100000, ai <= 200

  • analysis of idea

  • See the data range == == n, Q range significantly O ( n 2 ) O (n ^ 2) Pretreatment O ( 1 ) O (1) query,then it is a pure RMQ + ST
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+10;
int n;
 /*假设要查询的区间为 [ l, r ],我们用 L 表示区间 [ l , r ] 的长度,即 L = r - l + 1,下面用 k 表示 log L
 其中查询的话,区间长度 L 不一定刚好是 2 的多少次方,又因为 log L 是向下取整,那么 2^k 就有可能小于 L,这样的话,我们就不能直接用 f [ l ][ k ] 来表示答案,不然的话会有遗漏
正确的做法是我们就从 l 往右取 2^k 个(即 f [ l ][ k ]),从 r 往左取 2^k 个(即?f [ r - ( 1 << k ) + 1 ][ k ]),
这样就能保证区间 [ l , r ] 都被访问到了,重复计算的不用担心,这是计算最值而不是求和
 那么答案answer = max { f [ l ][ k ] , f [ r - ( 1 << k ) + 1 ][ k ]}*/
inline int read() {
    int cnt = 0;
    int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
    cnt *= f;
    return cnt;
}
int a[N],v[N],st[N][25];//ST[N][log 2 N]  
int s[N<<1];//s代表状态
inline int preRMQ(int l,int r){//预处理最大值 
	int j=0;
	while((1<<j)<=(r-l+1)){
		j++;
	}
	j--;
	return max(st[l][j],st[r-(1<<j)+1][j]);//数列中下标在[i,i+2的i次方-1]最大值 
}
signed main(){
	freopen("beautiful.in","r",stdin);
	freopen("beautiful.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=n;i++){
		memset(s,-1,sizeof(s));
		s[N]=i;// 每个i为一个状态 
		int q=0;
		for(int j=i-1;j>=1;j--){
			if(a[j]<=a[i]){
				q--;
				s[N+q]=j;//防止下标出界 
			}
			else{
				q++;s[N+q]=j;
			}
		}
		q=0;v[i]=i-s[N]+1;//状态长度 
		for(int j=i+1;j<=n;j++){
			if(a[i]<=a[j]){
				q++;//记录比他小的值的个数 
				if(s[N-q]!=-1){//i状态没有被重新更改 
					v[i]=max(v[i],j-s[N-q]+1);
				}
			}
			else{
				q--;
				if(s[N-q]!=-1){
					v[i]=max(v[i],j-s[N-q]+1);
				}
			}
		}
		st[i][0]=v[i];//初始化 st[i][0]=A[i] 
	}
	for(int j=1;(1<<j)<=n;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]);//处理ST表 
		}
	}
	int l,r,q;
	q=read();
	for(int i=1;i<=q;i++){
		l=read();r=read();
		printf("%d\n",preRMQ(l,r));
	}
	return 0;
}
Published 37 original articles · won praise 11 · views 1938

Guess you like

Origin blog.csdn.net/weixin_42750325/article/details/101996171