关闭

HDU 5701 中位数计数 (百度之星初赛)

262人阅读 评论(0) 收藏 举报
分类:

【题目链接】点击打开链接

【分析&解题思路】

首先对于第i个数,我们从i-1个数开始递减,分别与第i个数进行比较,假设比第i个数大的数的个数即为l,比第i个数小的数的个数即为r,dp[l-r=k]则为[比第i个数的数的个数][比第i个数的数的个数]多k个的区间个数,那要保证第i个数是区间内的中位数,我只需要在第i个数的右边找有多少个[比第i个数的数的个数][比第i个数的数的个数]多k个的区间,这样两个区间连接起来,正好[比第i个数的数的个数][比第i个数的数的个数]一样多,这样,第i个数就是此区间内的中位数

另外,因为数组下标必须为非负整数,故把数组的中心点移至8000,即dp[8000+k],这样就保证了下标一定是符合要求的

【AC代码】

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
typedef __int64 LL;
typedef unsigned __int64 LLU;
const int nn=110000;
const int inf=0x3fffffff;
const int mod=1000000007;
const LL inf64=(LL)inf*inf;
const double eps = 1e-12;
using namespace std;
int n;
int a[8100];
int ans[8100];
int tem[8100*2];
int main()
{
    int i,j;
    while(scanf("%d%",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            ans[i]=1;
        }
        for(i=1;i<=n;i++)
        {
            memset(tem,0,sizeof(tem));
            int ix=0;
            for(j=i-1;j>=1;j--)
            {
                if(a[j]<a[i])
                {
                    ix--;
                }
                else
                    ix++;
                tem[ix+8010]++;
                if(ix==0)
                    ans[i]++;
            }
            ix=0;
            for(j=i+1;j<=n;j++)
            {
                if(a[j]<a[i])
                    ix--;
                else
                    ix++;
                ans[i]+=tem[8010-ix];
                if(ix==0)
                    ans[i]++;
            }
        }
        for(i=1;i<=n;i++)
        {
            printf("%d%c",ans[i],i==n?'\n':' ');
        }
    }
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:318504次
    • 积分:15096
    • 等级:
    • 排名:第835名
    • 原创:1235篇
    • 转载:13篇
    • 译文:0篇
    • 评论:61条
    文章分类