多校联训 优美值 题解

题面:

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

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

【输入】

第一行输入整数n ,第二行输入n 个整数ai ,第三行输入整数 Q,代表有 Q 个区间,接下来 Q 行,每行两个整数 l, r(l ≤ r),表示区间的左右端点。

【输出】

对于每个区间的询问,输出答案

【数据范围】

对于 30% 的数据,满足 n,Q ≤ 50

对于 70% 的数据,满足 n,Q ≤ 2000

对于所有数据,满足 n ≤ 2000, Q ≤ 1000000,ai ≤ 1000000

首先我们会想到一个十分简单的但非正解做法:n^nlogn+一大堆常数通过对顶堆来求出每个位置的最大值;然后ST表nlogn处理就好了;

然后细细挖掘这道题,对于每个位置,把大于他的值变成1,否则变成0,然后求一段最大的区间使得区间总和是0,且包含该点;

这样n^nlogn+nlogn的算法就优化成了n^n+nlogn;

下面给出对顶堆的代码:

#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
template<class nT>
inline void read(nT& x)
{
	char c;while(c=getchar(),!isdigit(c));
	x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
}
const int MXR=1e6+1e5;
int a[MXR];
priority_queue<pair<int,int> >  q1,q2;//q1是大根堆,q2是小根堆 
int ans[MXR];
int f[MXR][25];
int n; 
int pre[MXR];
void build()
{
	inc(i,1,n) f[i][0]=ans[i];
	inc(j,1,20){
	    for(int i=1;i+(1<<j)-1<=n;i++){
	    	f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
	    }
	}
	inc(j,0,19){
		inc(i,(1<<j),(1<<(j+1))-1){
			if(i>MXR) break;
			pre[i]=j;
		}
	}
}
int main()
{
	read(n);
	inc(i,1,n) read(a[i]);
	inc(i,1,n){
		while(q1.size()) q1.pop();
		while(q2.size()) q2.pop();
		inc(j,i,n){
			if(q1.size()&&a[j]>q1.top().first) q2.push(make_pair(-a[j],j));
			else q1.push(make_pair(a[j],j));
			if((j-i+1)%2==0){
				continue;
			}
			while(q2.size()>(j-i+1)/2){
				q1.push(make_pair(-q2.top().first,q2.top().second));
				q2.pop();
			}
			while(q2.size()<(j-i+1)/2){
				q2.push(make_pair(-q1.top().first,q1.top().second));
				q1.pop();
			}			
			ans[q1.top().second]=max(ans[q1.top().second],(j-i+1));
		}
	}
	build();
	int q; read(q);
	inc(i,1,q){
		int x,y; read(x); read(y);
		int logg=pre[y-x+1];
		int anss=max(f[x][logg],f[y-(1<<logg)+1][logg]);
		printf("%d
",anss);
	}
	
}
/*
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
*/
原文地址:https://www.cnblogs.com/kamimxr/p/11747505.html