1. 程式人生 > >HDU 5701 中位數計數 (思維題)

HDU 5701 中位數計數 (思維題)

題目連結

 

中位數定義為所有值從小到大排序後排在正中間的那個數,如果值有偶數個,通常取最中間的兩個數值的平均數作為中位數。 

現在有nn個數,每個數都是獨一無二的,求出每個數在多少個包含其的區間中是中位數。 

Input

多組測試資料 

第一行一個數n(n≤8000)n(n≤8000) 

第二行nn個數,0≤0≤每個數≤109≤109,

Output

NN個數,依次表示第ii個數在多少包含其的區間中是中位數。

Sample Input

5
1 2 3 4 5

Sample Output

1 2 3 2 1

PS:這個題是一個很不錯的思維題,首先我們宣告一個ans陣列儲存答案,一個數組num儲存左邊右邊比當前數打或者小的數的個數,已a[i]來討論,有三種情況。

1.討論它左邊的區間,從(i-1)向左遍歷,注意一定是這樣遍歷,不然不能夠保證連續區間,然後宣告一個num記錄比它大或者比他小的數,遇到比它大的數,num++,反之num--,如果num==0,說明在他的左區間比他大的數和比它小的數個數一樣,它直接能夠是中位數,ans[i]++,因為num可以是負數,所以在陣列記錄的時候需要提前加個大數,直接num[maxn+sum]++。

2.討論它右邊的區間,從(i+1)向右遍歷。其他情況和向左遍歷的情況一樣。

3.同時討論a[i]的左右區間。直接ans[i]+=num[maxn-sum];說一下為什麼這樣可以。若是左邊有兩個比它大的,num記錄的num[maxn+2]等於1,需要在右邊右邊找兩個比它小的數num==-1。所以直接ans[i]+=num[maxn-(-2)]等於ans[i]+=num[maxn+2]。

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=8e3+10;
const int mod=10007;
const int inf=1e8;
#define me(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
typedef long long ll;
using namespace std;
int main()
{
    int n,a[maxn],ans[maxn];
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            ans[i]=1;
        }
        for(int i=1;i<=n;i++)
        {
            int num[maxn<<2],sum=0;
            me(num,0);
            for(int j=i-1;j>=1;j--)
            {
                if(a[j]>a[i])
                    sum++;
                else
                    sum--;
                if(sum==0)//他的左區間比他大的數和比它小的數個數一樣,它直接能夠是中位數
                    ans[i]++;
                num[maxn+sum]++;
            }
            sum=0;
            for(int j=i+1;j<=n;j++)
            {
                if(a[j]>a[i])
                    sum++;
                else
                    sum--;
                if(sum==0)//他的左區間比他大的數和比它小的數個數一樣,它直接能夠是中位數
                    ans[i]++;
                ans[i]+=num[maxn-sum];//加上左邊數量對應的數目
            }
        }
        for(int i=1;i<n;i++)
            printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
    return 0;
}