【题解】LuoGu1627:[CQOI2009]中位数

原题传送门
首先我们只需要知道每个数与指定数的大小关系就行了
所以将它们分别赋值成-1,0,1
然后求前缀和 s i s_i si
若存在 i , j ( i < j ) , s i = s j i,j(ii,j(i<j),si=sj,说明 a i + 1 a_{i+1} ai+1~ a j a_j aj是一个合理子串
所以指定数两遍分别开桶统计每个前缀和出现次数然后乘法原理

这里注意一点,若存在 i , j ( i < j ) , s i = s j i,j(ii,j(i<j),si=sj且指定数在 i , j i,j i,j之间,那么这个子串一定是奇数,易证

Code:

#include 
#define maxn 100010
using namespace std;
int n, b, cnt[2][maxn << 1];

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

int main(){
	n = read(), b = read();
	int flag = 0, s = n;
	cnt[0][n] = 1;
	for (int i = 1; i <= n; ++i){
		int a = read();
		if (a != b) s += a > b ? 1 : -1;
		++cnt[flag |= a == b][s];
	}
	long long ans = 0;
	for (int i = 0; i <= (n << 1); ++i)  ans += 1LL * cnt[0][i] * cnt[1][i];
	printf("%lld\n", ans);
	return 0;
}

你可能感兴趣的:(题解,LuoGu,LuoGu,题解)