【Bzoj1303】中位数图

来源:互联网 发布:海沧广电网络客服 编辑:程序博客网 时间:2024/06/05 20:45

题意

给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。


解析

因为数都是不重复的,所以可以把左边小于它的记为+1,大于的记为-1,统计前缀和f。同理,右边大于的记为1,小于的记为-1,统计前缀和g,那么,如果左边某个数出现某次数的方法种数等于右边的,就根据乘法原理统计答案,特别地,f[0]=g[0]=1。数组下标要做一点处理。


#include <cstdio>#include <algorithm>#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)using std :: max;using std :: min;const int maxx = (100000<<1) + 25;const int N = 100005;int n,m,x,y,z;int a[maxx],f[maxx],g[maxx];int ans,tmp,pos;int main(){    scanf("%d%d",&n,&m);    Rep( i , 1 , n ) scanf("%d",&a[i]);    Rep( i , 1 , n ) if(a[i] == m) pos = i;    f[N] = g[N] = 1;    Dnt( i , pos-1 , 0 ) tmp += (a[i]<m)? 1 : -1,f[tmp+N] ++;    tmp = 0;    Rep( i , pos+1 , n ) tmp += (a[i]>m)? 1 : -1,g[tmp+N] ++;    Rep( i , N-n , N+n ) ans += f[i]*g[i];    printf("%d",ans);    return 0;}
原创粉丝点击