BEAUTIFUL

DESCRIPTION:
一个长度为n 的序列,对于每个位置i 的数ai 都有一个优美值,其定义是:找到序列中最
长的一段[l, r],满足l<i<r,且[l, r] 中位数为ai(我们比较序列中两个位置的数的大小时,
以数值为第一关键字,下标为第二关键字比较。这样的话[l, r] 的长度只有可能是奇数),r - l
+ 1 就是i 的优美值。
接下来有Q 个询问,每个询问[l, r] 表示查询区间[l, r] 内优美值的最大值。
INPUT:
第一行输入n 接下来n 个整数,代表ai 接下来Q,代表有Q 个区间接下来Q 行,每行
两个整数 l, r 表示区间的左右端点
OUTPUT:
对于每个区间的询问,输出答案
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

数据范围:
30%: N,Q<50
70%:N,Q<2000

100%:N<2000,Q<100000,ai<200
对于所有数据,满足n  2000, Q <100000,ai <200

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; 
int main()
{
    freopen("beautiful.in","r",stdin);
    freopen("beautiful.out","w",stdout);
    static int a[2001],b[8001],v[2001],f[2001][2001];
    int *l(b+2000),*r(b+6000);
    int n(0),cnt(0);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",a+i);
    for(int i=1;i<=n;i++)
    {
        cnt=0;
        memset(b,0,sizeof(b));
        l[0]=r[0]=i;
        for(int j=i-1;j>0;j--)
        {
            if(a[j]>a[i])cnt++;
            else cnt--;
            l[cnt]=j;
        }
        cnt=0;
        for(int j=i+1;j<=n;j++)
        {
            if(a[j]>=a[i])cnt++;
            else cnt--;
            r[cnt]=j;
        }
        v[i]=0;
        for(int j=-n;j<=n;j++)
            if(l[j]&&r[-j])
                v[i]=max(v[i],r[-j]-l[j]+1);
    }    
    for(int i=1;i<=n;i++)
        f[i][i]=v[i];
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            f[i][j]=max(f[i][j-1],f[j][j]);
    int q(0);
    scanf("%d",&q);
    while(q)
    {
        q--;
        int lt(0),rt(0);
        scanf("%d%d",&lt,&rt);
        printf("%d
",f[lt][rt]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/JebediahKerman/p/6011310.html