1005E1 Median on Segments (Permutations Edition) 【思維+無序陣列求中位數】
阿新 • • 發佈:2018-11-20
題目:戳這裡
百度之星初賽原題:戳這裡
題意: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(){View Code10 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 }