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
Pretreatment
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;
}