九校联考-长沙市一中NOIP模拟Day1T3 优美序列(sequence)

问题描述

Lxy养了N头奶牛,他把N头奶牛用1..N编号,第i头奶牛编号为i。为了让奶牛多产奶,每天早上他都会让奶牛们排成一排做早操。奶牛们是随机排列的。在奶牛排列中,如果一段区间[L,R]中的数从小到大排列后是连续的,他认为这段区间是优美的。比如奶牛排列为:(3, 1, 7, 5, 6, 4, 2),区间[3,6]是优美的,它包含4,5,6,7连续的四个数,而区间[1,3] 是不优美的。Lxy的问题是:对于给定的一个区间[L,R](1<=L<=R<=N), 他想知道,包含区间[L,R]的最短优美区间,比如区间[1,3]的最短优美区间是[1,7]。

输入

第一行为一个整数N,表示奶牛的个数。
第二行为1到N的一个排列,表示奶牛的队伍。
第三行为一个整数M,表示有M个询问。
后面有M行,每行有两个整数L,R表示询问区间。

输出

输出为M行,每行两个整数,表示包含询问区间的最短优美区间。

输入输出样例

样例一输入

7
3 1 7 5 6 4 2
3
3 6
7 7
1 3

样例一输出

3 6
7 7
1 7

样例二输入

10
2 1 4 3 5 6 7 10 8 9
5
2 3
3 7
4 7
4 8
7 8

样例二输出

1 4
3 7
3 7
3 10
7 10

数据范围

15%的数据满足: 1 <=N,M <= 15;
50%的数据满足:1 <=N,M <= 1000。

大概是Day最简单的一道题了
在询问的区间中找到最大值和最小值,因为要连续,所以中间的值全部要取到,接着找所有要取的值里面最大和最小的位置.
由于这时候没考虑多包函进来的数字是否都在最开始的区间可以多次用每次询问出的答案接着询问,直到询问和给出的答案相同
ST表和线段树等log数据结构都能过,不过查询较多还是ST表更好??

#include<cstdio>
#include<algorithm>

#define ls now<<1
#define rs now<<1|1

using namespace std;

const int MAXN=100002;
const int inf=19260817;

int loc[MAXN],seq[MAXN];
int seqmax[MAXN<<2],seqmin[MAXN<<2];
int locmax[MAXN<<2],locmin[MAXN<<2];

void build(int l,int r,int now)
{
	if(l==r){
		seqmax[now]=seq[l];
		seqmin[now]=seq[l];
		locmax[now]=loc[l];
		locmin[now]=loc[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	seqmax[now]=max(seqmax[ls],seqmax[rs]);
	seqmin[now]=min(seqmin[ls],seqmin[rs]);
	locmax[now]=max(locmax[ls],locmax[rs]);
	locmin[now]=min(locmin[ls],locmin[rs]);
}

int queryseqmax(int l,int r,int ll,int rr,int now)
{
	if(ll>rr)return 0;
	if(ll>r||rr<l)return 0;
	if(l<=ll&&r>=rr)return seqmax[now];
	int mid=(ll+rr)>>1;
	return max(queryseqmax(l,r,ll,mid,ls),queryseqmax(l,r,mid+1,rr,rs));
}

int querylocmax(int l,int r,int ll,int rr,int now)
{
	if(ll>rr)return 0;
	if(ll>r||rr<l)return 0;
	if(l<=ll&&r>=rr)return locmax[now];
	int mid=(ll+rr)>>1;
	return max(querylocmax(l,r,ll,mid,ls),querylocmax(l,r,mid+1,rr,rs));
}

int queryseqmin(int l,int r,int ll,int rr,int now)
{
	if(ll>rr)return inf;
	if(ll>r||rr<l)return inf;
	if(l<=ll&&r>=rr)return seqmin[now];
	int mid=(ll+rr)>>1;
	return min(queryseqmin(l,r,ll,mid,ls),queryseqmin(l,r,mid+1,rr,rs));
}

int querylocmin(int l,int r,int ll,int rr,int now)
{
	if(ll>rr)return inf;
	if(ll>r||rr<l)return inf;
	if(l<=ll&&r>=rr)return locmin[now];
	int mid=(ll+rr)>>1;
	return min(querylocmin(l,r,ll,mid,ls),querylocmin(l,r,mid+1,rr,rs));
}

int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);	
	
	int n,m;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",seq+i);
		loc[seq[i]]=i;
	}
	build(1,n,1);
	scanf("%d",&m);
	while(m--){
		int l,r,_seqmax,_seqmin,ansl=0,ansr=0;
		scanf("%d %d",&l,&r);
		bool flag=0;
		while(l!=ansl||r!=ansr){
			if(flag)l=ansl,r=ansr;
			_seqmax=queryseqmax(l,r,1,n,1);
			_seqmin=queryseqmin(l,r,1,n,1);
			ansl=querylocmin(_seqmin,_seqmax,1,n,1);
			ansr=querylocmax(_seqmin,_seqmax,1,n,1);
			flag=1;
		}
		
	}
	return 0;
}
原文地址:https://www.cnblogs.com/shulker/p/9652643.html