中位数计数
转载声明:http://blog.csdn.net/jtjy568805874/article/details/51477656
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5701
个人想法:这次是我第一次写得博客,在平时我几乎没写过博客,我突然觉得写博客很重要,这是一个我的错题集,我想把我的想法分享给大家,平时也看到一些题解,完全就是粘贴的,说得不明不白,感觉和没写一样,这好没意思哦.所以我也想分享我做题过程.首先一开始我是想用划分树来写的,因为查询中位数用划分树就logn左右,只要枚举奇数的范围区间中的中位数就可以得到对应中位数的个数,然后再加n^2/2的循环,按道理应该不会超时,可是毫无意外的还是超时了,然后听到同学统计左右区间的比当前的数大的和小的个数就好了…可是我做了还是超时,然后,就没有然后了,实在想不到优化. 这是我转载的一个声明,实在是狠狠打了自己一巴掌,自己实在太蠢了…这也想不出来.╮(╯▽╰)╭。
分析:这题的意思是找到每个数在连续区间中作为中位数的次数,其实做一次题目样例就可以发现只需要统计奇数区间就行了,并不存在偶数区间的统计,偶数的统计还得获得两个数再做平均,这显然不是题目本意,好了我们可以向到枚举每个区间的中位数就好了,假设我当前的数是a[i],然后我算下一个是比a[i]大还是小,用个数组rmax[i]||rmin[i]记录下来, 然后扫描a[i]的左区间,同样的,用数组lmax[i],lmin[i] 记录下来,直接lmin[i]+rmin[i]==rmax[i]+lmax[i] ans就加一,然后继续往右拓展,记录再下一个数是大还是小,再往左扫描,可是显然这样子是会超时的,这几乎是n3的算法,从我看了这博客之后我就发现了一个问题!!重复计算!!,因为在往右扫面的时候,其实rmax[i]-rmin[i]=x是变化 而且会重复出现次数,只要我扫面一编a[i]右边的值,然后就知道右边位置需要大的个数和小的个数就多少,然后扫面左边的时候,和右边做个叠加就好了,因为这是个偏离中位数的思想,这里有点点说不清,具体看一下代码就应该大概明白了.
代码:
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
int N;
int Pian[20000];
int Num[8005];
int main()
{
#ifdef OUT
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
while(scanf("%d",&N)!=EOF)
{
bool flag=true;
for(int i=1;i<=N;i++)
{
scanf("%d",&Num[i]);
}
for(int i=1;i<=N;i++)
{
memset(Pian,0,sizeof(Pian));
int x=0;
Pian[8005+x]++;
for(int j=1;(i+j)<=N;j++)
{
if(Num[i+j]>Num[i])x++;
else x--;
Pian[8005+x]++;//这就是左边偏离重复的统计
}
x=0;
int ans=Pian[8005];//先把右边的没偏离的加上,虽然看了点blog,大概思想有了,但是还是写错,忘记先统计右边,wa很多次。
for(int j=1;(i-j)>=1;j++)
{
if(Num[i-j]>Num[i])x++;
else x--;
ans+=Pian[8005-x];//然后把左边缺少相应的个数向右边拍过去,那就是答案.
}
if(flag){printf("%d",ans);flag=false;}
else printf(" %d",ans);
}
printf("\n");
}
return 0;
}