[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 }

 

posted @ 2019-01-24 15:10  AC-Evil  阅读(129)  评论(0编辑  收藏  举报