题目
DescriptionInput
Output
Sample Input1
7
3 1 7 5 6 4 2
3
3 6
7 7
1 3
Sample Input2
10
2 1 4 3 5 6 7 10 8 9
5
2 3
3 7
4 7
4 8
7 8
Sample Output1
3 6
7 7
1 7
Sample Output2
1 4
3 7
3 7
3 10
7 10
Data Constraint
分析
区间 [ l , r ] [l,r] [l,r]是优美区间当且仅当 max i = l r a i − min i = l r a i = r − l + 1 \max\limits_{i=l}^{r}a_i-\min\limits_{i=l}^{r}a_i=r-l+1 i=lmaxrai−i=lminrai=r−l+1,换句话说,至少 [ min i = l r a i , max i = l r a i ] [\min\limits_{i=l}^{r}a_i,\max\limits_{i=l}^{r}a_i] [i=lminrai,i=lmaxrai]里面的所有数要在答案的区间里面,所以记录值为 i i i的元素的位置 p o s [ i ] pos[i] pos[i],那么求原问题的答案变为了求 [ p o s [ min i = l r a i ] , p o s [ max i = l r a i ] ] \left[pos\left[\min\limits_{i=l}^{r}a_i\right],pos\left[\max\limits_{i=l}^{r}a_i\right]\right] [pos[i=lminrai],pos[i=lmaxrai]]的答案,递归求解,当前区间 max i = l r a i − min i = l r a i = r − l + 1 \max\limits_{i=l}^{r}a_i-\min\limits_{i=l}^{r}a_i=r-l+1 i=lmaxrai−i=lminrai=r−l+1时就是答案了,ST表RMQ。时间复杂度 O ( 疯 狂 卡 常 可 以 过 ) O(疯狂卡常可以过) O(疯狂卡常可以过)。
代码
84分。有人过了我就是open yellow gun。
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int read(){
int x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=x*10+(c^48),c=getchar();
return f?-x:x;
}
void print(int x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
#define MAXN 100000
int N,M;
int A[MAXN+5],pos[MAXN+5];
int Log2[MAXN+5],Pow2[MAXN+5];
int Ansl,Ansr;
#define LOG 17
int STMax[2][MAXN+5][LOG+5];
int STMin[2][MAXN+5][LOG+5];
void Init(){
for(int i=1;i<=N;i++)
Log2[i]=log2(i);
for(int i=0;i<=LOG;i++)
Pow2[i]=1<<i;
for(int i=1;i<=N;i++)
STMax[0][i][0]=STMin[0][i][0]=A[i],
STMax[1][i][0]=STMin[1][i][0]=pos[i];
for(int j=1;j<=LOG;j++)
for(int i=1;i+Pow2[j-1]<=N;i++)
STMax[0][i][j]=max(STMax[0][i][j-1],STMax[0][i+Pow2[j-1]][j-1]),
STMin[0][i][j]=min(STMin[0][i][j-1],STMin[0][i+Pow2[j-1]][j-1]),
STMax[1][i][j]=max(STMax[1][i][j-1],STMax[1][i+Pow2[j-1]][j-1]),
STMin[1][i][j]=min(STMin[1][i][j-1],STMin[1][i+Pow2[j-1]][j-1]);
}
int QueryMax(int id,int l,int r){
int k=Log2[r-l+1];
return max(STMax[id][l][k],STMax[id][r-Pow2[k]+1][k]);
}
int QueryMin(int id,int l,int r){
int k=Log2[r-l+1];
return min(STMin[id][l][k],STMin[id][r-Pow2[k]+1][k]);
}
void Solve(int l,int r){
int Max=QueryMax(0,l,r),Min=QueryMin(0,l,r);
int L=QueryMin(1,Min,Max),R=QueryMax(1,Min,Max);
Max=QueryMax(0,L,R),Min=QueryMin(0,L,R);
if(Max-Min==R-L){
Ansl=L,Ansr=R;
return;
}
Solve(L,R);
}
int main(){
freopen("sequence.in" ,"r", stdin);
freopen("sequence.out","w",stdout);
N=read();
for(int i=1;i<=N;i++)
pos[A[i]=read()]=i;
Init();
M=read();
while(M--){
int L=read(),R=read();
Solve(L,R);
print(Ansl),putchar(' '),print(Ansr),putchar('\n');
}
}