zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/zmin/p/9989223.html
Copyright © 2011-2022 走看看