HDU4908 - BestCoder Sequence(BestCoder Round #3 计数)

来源:互联网 发布:java能做什么游戏 编辑:程序博客网 时间:2024/06/05 21:12

题目链接 HDU4908

【题意】在1~n的一个排列中找到以m为中位数的连续子序列有多少个。

【分析】先求出sum[i][j],表示左边序列长度(不算m)为奇数或者偶数(j表示奇偶)的时候 大于m个数-小于m个数 的序列个数。
然后遍历m右边长度为奇数个(这时整个序列是奇数个 奇数+奇数+1 = 奇数 或者 偶数+偶数+1 = 奇数)时
小于m-大于m 的个数s时,累加上所有sum[小于m个数-大于m个数][()&1];
因为 左边大于m的数的个数b1+右边大于m的个数b2 = 左边小于m的个数s1+右边小于m的个数s2
这正是当遍历右边的时候 右边小于m个数s2-右边大于m个数b2 = 左边大于m个数b1-左边小于m个数s1(上式移项得到)

 

【AC CODE】 78ms

#include <cstdio>#include <cstring>#define MAXN 40000int a[MAXN+10], sum[2*MAXN+10][2];//sum[i][j]表示左边序列长度(不算m)为奇数或者偶数(j表示奇偶)的时候 大于m个数-小于m个数 的序列个数,/*然后遍历m右边长度为奇数个(这时整个序列是奇数个 奇数+奇数+1 = 奇数 或者 偶数+偶数+1 = 奇数)时小于m-大于m 的个数s时,累加上所有sum[小于m个数-大于m个数][()&1];因为 左边大于m的数的个数b1+右边大于m的个数b2 = 左边小于m的个数s1+右边小于m的个数s2这正是当遍历右边的时候 右边小于m个数s2-右边大于m个数b2 = 左边大于m个数b1-左边小于m个数s1(上式移项得到)*/int main(){#ifdef SHY    freopen("e:\\1.txt","r",stdin);#endif    int n,m;    while(~scanf("%d %d%*c", &n, &m))    {        int ans, mid, p = 0;        memset(sum,0,sizeof(sum));        for(int i = 1; i <= n; i++)        {            scanf("%d%*c", &a[i]);            if(m == a[i]) mid = i;        }sum[MAXN][0] = 1;//只有一个m的时候        for(int i = mid-1; i >= 1; i--)        {            if(a[i] > m) p++;else p--;sum[p+MAXN][(mid-i)&1]++;        }p = 0;ans = sum[MAXN][0];//先加上所有p为0时的偶数个序列        for(int i = mid+1; i <= n; i++)        {if(a[i] > m) p--;else p++;ans += sum[p+MAXN][(i-mid)&1];        }        printf("%d\n", ans);    }    return 0;}


 

0 0
原创粉丝点击