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;
    }

     

  • 相关阅读:
    纯CSS气泡对话框
    使用JAVASCRIPT实现的 单行文字 逐个文字变色,可以循环控制
    数字转换成中文汉字
    jquery如何在对表格添加删除后再对其前面加上顺序的序列号
    情路
    【缅怀妈妈系列诗歌】之二十四:一份永不忘却的思念
    我等你,千年之后
    赢道在手,前程无忧
    为你感动
    你为什么对我如此冷漠
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7601410.html
Copyright © 2011-2022 走看看