BZOJ-1303 [CQOI2009]中位数图(前缀和+计数)
题目描述
给出 \(1,2,\cdots,n(n\leq 10^5)\) 的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是 \(b\)。中位数是指把所有元素从小到大排列后,位于中间的数。
分析
读入的时候把大于 \(b\) 的数赋值为 \(1\),小于 \(b\) 的数赋值为 \(-1\),\(b\) 的下标设为 \(pos\)。设 \(l[i]\) 为 \(pos\) 左边的后缀和为 \(i\) 的后缀数目,\(r[i]\) 为 \(pos\) 右边的前缀和为 \(i\) 的前缀数目。枚举 \(-10^5\leq x\leq 10^5\),\(l[x]\) 可以与 \(r[-x]\) 匹配,方案数为 \(l[x]\times r[-x]\)。答案即为 \(\displaystyle\sum_{i=-10^5}^{10^5}l[i]\times r[-i]\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N+10],l[4*N+10],r[4*N+10];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main()
{
int n,b,pos;
cin>>n>>b;
for(int i=1;i<=n;i++)
{
a[i]=read();
if(a[i]>b)
a[i]=1;
else if(a[i]==b)
pos=i;
else
a[i]=-1;
}
l[N+0]=r[N+0]=1;
int sum=0;
for(int i=pos-1;i>=1;i--)
{
sum=sum+a[i];
l[N+sum]++;
}
sum=0;
for(int i=pos+1;i<=n;i++)
{
sum=sum+a[i];
r[N+sum]++;
}
long long ans=0;
for(int i=0;i<=N+100000;i++)
ans=ans+l[i]*r[2*N-i];
cout<<ans<<endl;
return 0;
}
posted on 2020-12-07 12:14 DestinHistoire 阅读(53) 评论(0) 编辑 收藏 举报