优美序列

文章目录

题目

Description题目描述Input
输入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
数据范围1
数据范围2

分析

区间 [ 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=lmaxraii=lminrai=rl+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=lmaxraii=lminrai=rl+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');
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值