1. 程式人生 > >1005E1 Median on Segments (Permutations Edition) 【思維+無序陣列求中位數】

1005E1 Median on Segments (Permutations Edition) 【思維+無序陣列求中位數】

題目:戳這裡

百度之星初賽原題:戳這裡

題意:n個不同的數,求中位數為m的區間有多少個。

解題思路:

此題的中位數就是個數為奇數的陣列中,小於m的數和大於m的數一樣多,個數為偶數的陣列中,小於m的數比大於m的數少一。因此,維護比m小和比m大的數就行。

m~n進行處理,比m大的cnt++,比m小的cnt--,用vis陣列記錄每個cnt值的個數。

m~1再進行處理,比m大的cnt++,比m小的cnt--,ans+=vis[cnt]+vis[cnt+1],vis[cnt]可以理解為是右邊有cnt個比m大的數的情況(n為奇數,vis[cnt+1]是右邊有cnt個比m大的數的情況(n為偶數。(當然真正的數值並不代表這個意思,因為出現比m小的數時cnt--了,在這裡形容是為了便於理解。

這樣操作的意思是,先預處理[pos[m],r]的所有情況,在遍歷[l,pos[m]]的所有情況時,直接求出答案。

程式碼比文字好理解:

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 const int maxn = 1e6+10;
 4 const int inf = 0x3f3f3f3f;
 5 const ll mod = 998244353;
 6 using namespace std;
 7 int a[maxn];
 8 map<int,int>vis;
 9 int main(){
10 int n, m; 11 scanf("%d %d", &n, &m); 12 int pos = 0; 13 for(int i = 1; i <= n; ++i) { 14 scanf("%d",a+i); 15 if(a[i] == m) pos = i; 16 } 17 int cnt = 0; 18 for(int i = pos; i <= n; ++i) { 19 if(a[i] > m) ++cnt; 20 if(a[i] < m) --cnt;
21 vis[cnt]++; 22 } 23 cnt = 0; 24 ll ans = 0; 25 for(int i = pos; i >= 1; --i) { 26 if(a[i] > m) --cnt; 27 if(a[i] < m) ++cnt; 28 ans += vis[cnt]+vis[cnt+1];//此時m左邊的大小情況為cnt,要找右邊為cnt和cnt+1的情況 29 } 30 printf("%lld\n", ans); 31 return 0; 32 }
View Code