题解:P9053 [PA2021] Ranking sklepów internetowych
__rnfmabj__ · · 题解
题目大意
题目传送门
给定长为
定义区间
求所有
理清思路
首先很显然的一件事是最大值一定是
然后我们仔细想想,若是想要最大值是
既然知道了最大值以及中位数
知道了这一点后,我们就可以预处理出大于该中位数
代码
有了综上所述的思路之后,第一个问题时候怎样找左值
第二个问题是如何判越界,如果我们当前要补
AC code
#include <bits/stdc++.h>
using namespace std;
long long n,ans,ansl,a,bot[3000010],l=INT_MAX,r=1,k,L,s;
//ans为所求最大值,bot用于存每个数字的位置,l和r代表最左值和最右值,L是区间长度,k是所需长度,s代表要补几位
int main(){
scanf("%lld",&n);
ans=2*n+1;//z计算最大值
for (int i=1;i<=n;i++){
scanf("%lld",&a);
a*=2;//我直接乘二存的,便于后面求值
bot[a]=i;//记录下标
}
for (int i=n*2;i>n;i--){//枚举所有可行的中位数
if (bot[i]==0)bot[i]=bot[i-1];//如果没有被标记过,说明是中位数是,让他的下标等于比他大的值,再去求 l 和 r
r=max(bot[i],r);
l=min(bot[i],l);//寻找左值和右值
k=ans-i,L=r-l+1,s=k-L;//计算
if (L<=k){
ansl+=s+1;//统计答案
if (l<=s)ansl-=(s-l+1);
if (r+s>n)ansl-=(r+s-n);//判断越界
}
}
printf("%lld %lld",ans,ansl);//输出
return 0;//完结撒花
}