【题目链接】点击打开链接
【分析&解题思路】
首先对于第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;
}