bzoj 303: [CQOI2009]中位数图【前缀和+瞎搞】

处理出一个序列c,a[i]>b,c[i]=1;a[i]b,c[i]=0;a[i]<b,c[i]=-1,然后s为c的前缀和,设w为b在a序列里的下标
注意到子序列一定横跨w,并且一个符合条件的(l,r)一定满足s[r]-s[l-1]
0,也就是序列内大于b的数小于b的数,
所以对0w-1的s存一个mp,mp[i]表示0w-1中s[]
i的点有多少,然后枚举右端点w~n,每次答案加上当前枚举的右端点i的mp[s[i]],也就是找出有多少个符合要求的左端点

#include<iostream>
#include<cstdio>
using namespace std;
const int N=200005;
int n,a[N],b,w,s[N],mp[N],ans;
int read()
{
	int r=0,f=1;
	char p=getchar();
	while(p>'9'||p<'0')
	{
		if(p=='-')
			f=-1;
		p=getchar();
	}
	while(p>='0'&&p<='9')
	{
		r=r*10+p-48;
		p=getchar();
	}
	return r*f;
}
int main()
{
	n=read(),b=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		if(a[i]==b)
			w=i,s[i]=s[i-1];
		else
			s[i]=s[i-1]+((a[i]>b)?1:-1);
	}
	for(int i=1;i<=w;i++)
		mp[s[i-1]+n]++;
	for(int i=w;i<=n;i++)
		ans+=mp[s[i]+n];
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-09-13 15:33  lokiii  阅读(120)  评论(0编辑  收藏  举报