hdu 4908 BestCoder Sequence
http://acm.hdu.edu.cn/showproblem.php?pid=4908
有人定义了一种数串 数串的长度是奇数 且M在其中是中位数。。。
中位数 中间大的数 就是数串中比它的大的个数与比它小的个数是相等的
给定N个数 1~N中每个数都会出现一次 从其中找出满足BestCoder Sequence的个数 数串中的数是连续的
刚看到这个题的时候以为那个数处在处在数串中间位置就可以了 就直接写了 WA了三发 感觉没什么trick啊
后来发现是中位数 然后就没什么思路了。。。。
读取数字的时候把M值的位置记录下来记为pos 然后从pos开始 遍历到1 用low high去记录比M小和大的数的个数
对于每一个位置的比例都将num[x][high-low]的值加一 x用来表示i与pos的距离是奇数还是偶数
num[0][0]一定是1 用来表示单个M的情况 将ans的初值赋为它
然后从pos+1开始遍历到n 同样用low high去存储(记得将low high赋初值为0)
ans的值去加num[x][low-high]的值 表示 距离pos的奇偶性相同且左边high-low等于右边low-high
表示左边比M大的个数与右边小于M的个数。。。最后输出ans即可
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 40005
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
using namespace std;
#define f(x) (x+40005)
int num[2][MAXN*2];
int a[MAXN];
int main()
{
//freopen("ceshi.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int pos=0;
MEM(num,0);
FOR(i,1,n)
{
scanf("%d",&a[i]);
if(a[i]==m) pos=i;
}
int high=0,low=0;
FOV(i,pos,1)
{
if(a[i]<m) low++;
if(a[i]>m) high++;
num[(pos-i)&1][f(high-low)]++;
}
int ans=num[0][f(0)];
high=low=0;
FOR(i,pos+1,n)
{
if(a[i]<m) low++;
if(a[i]>m) high++;
ans+=num[(i-pos)&1][f(low-high)];
// cout<<f(low-high)<<" "<<num[(i-pos)&1][f(low-high)]<<endl;
}
printf("%d\n",ans);
}
return 0;
}