zoukankan      html  css  js  c++  java
  • BZOJ1303: [CQOI2009]中位数图

    【传送门:BZOJ1303


    简要题意:

      给出一条n个数的序列,保证序列里的数为1~n,且互不相等,再给出一个数b,求出以b为中位数的长度为奇数的子序列个数


    题解:

      显然要你求以b为中位数的长度为奇数的子序列,其实就是求包含b的,以b为中位数的子序列,因为序列中的数互不相等,而且求的是奇数长度

      那我们把序列中大于b的,改值为-1,小于b的,改值为1,等于b,就是b的位置,直接记录b的位置

      那显然就是一个求前缀和问题,首先定义L,R数组,分别表示以b所在的位置向前后延伸所得到的和的个数

      简单地用样例来说明:

       7   4
       5   7   2   4   3   1   6

      -1  -1   1   0   1   1  -1

      b的位置是4,向前后延伸,先向前,向前一位后,L[1]++,向前两位后,L[1+(-1)=0]++,向前三位后,L[0-1=-1]++,就是这样,R数组的求法也是这样

      那么答案就是ΣL[i]*R[-i](0<=i<=n)

      那么因为C++中的数组是访问不到负数的,所以就把得到的和加上n再记录到L数组,这样求解的时候就是ΣL[i+n]*R[n-i](0<=i<=n)


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int a[110000],s[110000];
    int mid[110000];
    int L[210000];
    int R[210000];
    int main()
    {
        int n,b;
        scanf("%d%d",&n,&b);
        int x=0;
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]>b) s[i]=-1;
            if(a[i]<b) s[i]=1;
            if(a[i]==b) x=i;
        }
        int sum=0;
        L[n]=1;R[n]=1;
        for(int i=x-1;i>=1;i--)
        {
            sum+=s[i];
            L[sum+n]++;
        }
        int ans=0;
        sum=0;
        for(int i=x+1;i<=n;i++)
        {
            sum+=s[i];
            R[sum+n]++;
        }
        for(int i=-n;i<=n;i++)
        {
            ans+=L[i+n]*R[n-i];
        }
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    前端模板Nunjucks简介
    git提交时支持文件名大小写的修改
    多行文本加省略号的处理方法
    前端性能优化实践方案总结
    使用gulp工具生成svgsprites
    koa简介
    JSX语法简介
    踩坑所引发出的appendChild方法的介绍
    React业务实践
    javascript--数组
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7601410.html
Copyright © 2011-2022 走看看