[CQOI2009]中位数
这道题的题意很显然。首先区间一定包括p,其次区间一定满足p左边右边大于p的数的个数和小于p的相等,于是将p左边和右边大于p和小于p的个数统计下。如果开二维数组记录空间太大了,事实上只要记录它们的差值即可。最后将差值能互补的乘起来加到答案里即可。具体做法见以下代码。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 #define re register 9 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 10 #define repd(i, a, b) for (re int i = a; i >= b; --i) 11 #define maxx(a, b) a = max(a, b); 12 #define minn(a, b) a = min(a, b); 13 #define LL long long 14 #define inf (1 << 30) 15 16 inline int read() { 17 int w = 0, f = 1; char c = getchar(); 18 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 19 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 20 return w * f; 21 } 22 23 const int maxn = 1e5 + 5; 24 25 int n, a[maxn], k, p, l[maxn << 1], r[maxn << 1]; 26 int *ll = &l[maxn], *rr = &r[maxn]; 27 int L = 0, R = 0; 28 29 LL sum = 0; 30 31 int main() { 32 n = read(), k = read(); 33 rep(i, 1, n) { 34 a[i] = read(); 35 if (a[i] == k) p = i; 36 } 37 ll[0] = rr[0] = 1; 38 39 int x = 0; 40 repd(i, p-1, 1) { 41 if (a[i] > a[p]) x++; else x--; 42 ll[x]++; 43 maxx(R, x); 44 minn(L, x); 45 } 46 x = 0; 47 rep(i, p+1, n) { 48 if (a[i] < a[p]) x++; else x--; 49 rr[x]++; 50 } 51 52 rep(i, L, R) sum += (LL)ll[i] * rr[i]; 53 54 printf("%lld", sum); 55 56 return 0; 57 }