1303: [CQOI2009]中位数图
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1974 Solved: 1268
[Submit][Status][Discuss]
Description
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
Input
第一行为两个正整数n和b ,第二行为1~n 的排列。
Output
输出一个整数,即中位数为b的连续子序列个数。
Sample Input
7 4
5 7 2 4 3 1 6
Sample Output
4
HINT
第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}
N<=100000
Source
题解:
发现了一个方法:
预处理一个权值数组,如果当前位置小于b为-1大于b为1,等于b为0
应用前缀和的思想,去做两个数组lsum,rsum。
不过,会出现负权,都+n即可
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define maxn 100010
int n,b;
int a[maxn],qz[maxn],ans=0,loc;
int lsum[2*maxn],rsum[2*maxn],sum;
int main()
{
n=read(),b=read();
for (int i=1; i<=n; i++)
{a[i]=read();if (a[i]==b) loc=i;}
for (int i=1; i<=n; i++)
if (a[i]<b) qz[i]=-1; else qz[i]=1;
lsum[n]=rsum[n]=1;
sum=0;
for (int i=loc-1; i>=1; i--)
sum+=qz[i],lsum[sum+n]++;
sum=0;
for (int i=loc+1; i<=n; i++)
sum+=qz[i],rsum[sum+n]++;
for (int i=0; i<=2*n; i++) ans+=lsum[i]*rsum[2*n-i];
printf("%d\n",ans);
return 0;
}