題意
n個數字,問m是多少個區間的中位數?偶數個數字的區間中位數認爲是中間靠左的那個數字,比如(1,3,7,8)中位數爲3。
E1:這n個數字是1~n的一個排列
E2:n個數字,數字大小不超過2e5
題解
做法①(可過E1,過不了E2):
思路請看:51Nod ~ 1682 ~ 中位數計數 (思維)
- #include <bits/stdc++.h>
- using namespace std;
- const int MAXN = 2e5+5;
- const int FIX = 2e5;
- typedef long long LL;
- int n, m, a[MAXN], pos, b[MAXN*2];
- int main()
- {
- scanf(“%d%d”, &n, &m);
- for (int i = 0; i < n; i++)
- {
- scanf(“%d”, &a[i]);
- if (a[i] == m) pos = i;
- }
- int cnt = 0;
- LL ans = 0;
- for (int i = pos; i >= 0; i–)
- {
- if (a[i] > m) cnt++;
- if (a[i] < m) cnt–;
- b[FIX+cnt]++;
- }
- cnt = 0;
- for (int i = pos; i < n; i++)
- {
- if (a[i] > m) cnt++;
- if (a[i] < m) cnt–;
- ans += b[FIX-cnt];
- ans += b[FIX-cnt+1];
- }
- printf(“%lld\n”, ans);
- return 0;
- }
- /*
- 5 4
- 2 4 5 3 1
- */
做法②(E1,2均可過):
中位數小於等於m的區間 - 小於等於m-1的區間=中位數等於m的區間 ,現在我們需要搞一個計算中位數小於等於x的區間個數的函數。首先如果中位數小於等於x,那麼<=x的數字一定大於>x的數字,我們記<=x的爲+1,>x的數字記爲-1,我們用變量s記錄這個值,如果對於[L,R]區間(L<R),L位置時的s小於R位置時的s,證明[L,R]區間是一個符合要求的區間。
枚舉右端點,維護s變量,對於右端點 R,怎麼得到s_L <= s_R 的 L 的個數呢?
O(n)做法:
數組cnt[i]用於統計 s = i 的點的個數(由於s有負值所以我們以n作爲0點即可),add維護s_L <= s_i 的 L 的個數
如果當前元素a[i]<=x,s要++,那麼對於 i 位置符合要求的點比 i-1 多了cnt[++s]個
如果當前元素a[i]>x,s要–,那麼對於 i 位置符合要求的點比 i-1 少了cnt[s–]個
統計答案,每次ans+=add即可,最終ans就是中位數大於等於x的區間數。
- #include <bits/stdc++.h>
- using namespace std;
- const int MAXN = 2e5+5;
- typedef long long LL;
- int n, m, a[MAXN], cnt[MAXN*2];
- LL slove(int x)
- {
- memset(cnt, 0, sizeof(cnt));
- int s = n; cnt[n] = 1;
- LL add = 0, ans = 0;
- for (int i = 0; i < n; i++)
- {
- if (a[i] <= x) add += cnt[++s];//add += cnt[++s]同s++; add += cnt[s];
- else add -= cnt[s--];//add -= cnt[s--]同add -= cnt[s]; s--;
- cnt[s]++;
- ans += add;
- }
- return ans;
- }
- int main()
- {
- scanf("%d%d", &n, &m);
- for (int i = 0; i < n; i++) scanf("%d", &a[i]);
- printf("%lld\n", slove(m) - slove(m-1));
- return 0;
- }
- /*
- 5 4
- 1 4 5 60 4
- */
O(n*logn)(BIT做法):
數組cnt[i]用於統計 s = i 的個數(由於s有負值所以我們以n作爲0點即可)
BIT維護cnt[s]這個數組,枚舉右端點,每次對於當前右端點,查詢有cnt中有多少個小於等於s的值。
- #include <bits/stdc++.h>
- using namespace std;
- const int MAXN = 2e5+5;
- typedef long long LL;
- int n, m, a[MAXN];
- struct BIT
- {
- int n, c[MAXN*2];
- void init (int n)
- {
- this->n = n;
- memset(c, 0, sizeof(c));
- }
-
- void add(int p, int x)
- {
- for (int i = p; i <= n; i += i&-i)
- c[i] += x;
- }
-
- int sum(int p)
- {
- int ans = 0;
- for (int i = p; i >= 1; i -= i&-i)
- ans += c[i];
- return ans;
- }
- }bit;
- LL slove(int x)
- {
- bit.init(2*n+1);
- bit.add(n+1, 1);
- int s = n+1;
- LL ans = 0;
- for (int i = 1; i <= n; i++)
- {
- if (a[i] <= x) s++;
- else s--;
- bit.add(s, 1);
- ans += bit.sum(s);
- }
- return ans;
- }
- int main()
- {
- scanf("%d%d", &n, &m);
- for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
- printf("%lld\n", slove(m) - slove(m-1));
- return 0;
- }
- /*
- 5 4
- 1 4 5 60 4
- */
</div>