20170711


T2:

一个长度为 n 的序列,对于每个位置 i 的数 ai 都有一个优美值,其定义是:找到序列中最长的一段 [l,r] ,满足 l≤i≤r,且 [l,r] 中位数为ai(我们比较序列中两个位置的数的大小时,以数值为第一关键字,下标为第二关键字比较。这样的话 [l,r] 的长度只有可能是奇数),r-l+1 就是 i 的优美值。

接下来有 Q 个询问,每个询问 [l,r] 表示查询区间 [l,r] 内优美值的最大值。

输入




16 19 7 8 9 11 20 16 

3 8 
1 4 
2 3 
1 1 
5 5 
1 2 
2 8 
7 8

输出








3
先对于每个数求出它的优美值,再找区间最大值。
#include<bits/stdc++.h>
using namespace std;
int a[2005],big1[2005],sum1[2005],sum2[2005],loc1[20005],loc2[20005];
int n,q,f[2005],fs[2005][2005];

int main(){
	//freopen("beautiful.in","r",stdin);
	//freopen("beautiful.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int i=1;i<=n;++i){
		memset(loc1,0,sizeof(loc1));
		memset(loc2,0,sizeof(loc2));
		memset(sum1,0,sizeof(sum1));
		memset(sum2,0,sizeof(sum2));
		loc1[n]=i;loc2[n]=i;
		int min1=n,max1=n,min2=n,max2=n;
		for(int j=i-1;j>=1;--j){
			if(a[j]>a[i]) sum1[j]=sum1[j+1]+1;
			else sum1[j]=sum1[j+1]-1;
			loc1[sum1[j]+n]=j;
			max1=max(max1,sum1[j]+n);
			min1=min(min1,sum1[j]+n);
		}
		for(int j=i+1;j<=n;++j){
			if(a[j]<a[i]) sum2[j]=sum2[j-1]-1;
			else sum2[j]=sum2[j-1]+1;
			loc2[sum2[j]+n]=j;
			max2=max(max2,sum2[j]+n);
			min2=min(min2,sum2[j]+n);
		}
		int ans=0;
		for(int j=min1;j<=max1;++j){
			if(loc2[2*n-j]!=0) ans=max(ans,loc2[2*n-j]-loc1[j]+1);
		}
		f[i]=ans; //求优美值,写得有点累赘
	}
	for(int i=1;i<=n;++i) fs[i][i]=f[i];
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j){
			if(f[j]>fs[i][j-1]) fs[i][j]=f[j];
			else fs[i][j]=fs[i][j-1];//i到j区间最大值,可以用RMQ
		}
	scanf("%d",&q);
	for(int i=1;i<=q;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		cout<<fs[x][y]<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值