zoukankan      html  css  js  c++  java
  • 【HDU】4908 (杭电 BC #3 1002题)BestCoder Sequence ——哈希 Prime

    BestCoder Sequence

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 573    Accepted Submission(s): 201


    Problem Description
    Mr Potato is a coder.
    Mr Potato is the BestCoder.

    One night, an amazing sequence appeared in his dream. Length of this sequence is odd, the median number is M, and he named this sequence as Bestcoder Sequence.

    As the best coder, Mr potato has strong curiosity, he wonder the number of consecutive sub-sequences which are bestcoder sequences in a given permutation of 1 ~ N.
     
    Input
    Input contains multiple test cases. 
    For each test case, there is a pair of integers N and M in the first line, and an permutation of 1 ~ N in the second line.

    [Technical Specification]
    1. 1 <= N <= 40000
    2. 1 <= M <= N
     
    Output
    For each case, you should output the number of consecutive sub-sequences which are the Bestcoder Sequences
     
    Sample Input
    1 1
    1
    5 3
    4 5 3 2 1
     
    Sample Output
    1 3
    Hint
    For the second case, {3},{5,3,2},{4,5,3,2,1} are Bestcoder Sequence.
     
    Source
     
    题意:给出1~n的一个排列,并给出其中一个数m,让你在这个序列中找出一个子序列,使得m是这个子序列的中位数。
     
    题解:中位数,即该序列按大小排序后,处于该序列中间的一个数,比如4,3,5中 4就是中位数,即该序列中比m大的数的个数与比m小的数的个数相等。
    从m的位置先往左边遍历,累计从m出发到第一个数的过程中,比m大的数的个数leftma 和比m小的数的个数leftmi。
    从m的位置再往右边遍历,累计从m出发到最后一个数的过程中,比m打的数的个数为rightma 和比m小的数的个数rightmi。
    如果存在序列,那么就是leftma+rightma == leftmi + rightmi 两边交换下 即满足 leftma-leftmi == rightmi-rightma;
    那么我们可以在往左遍历的过程中,将t = leftma-leftmi的值出现的次数采用哈希的形式储存起来,比如用table1[]保存负数,table2[]保存非负数,同时特判t = 0的情况。
    接着在往右遍历的过程中,使用t = rightmi-rightma定位哈希表中的位置,并ans+=table[t],同时特判t = 0的情况;(t = 0时此时只需要左半边或者又半边就能组成合法序,所以需要特判)
    最后即为结果。
     
    AC代码如下:
     
     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 const int LEN = 40040;
     5 
     6 int arr[LEN];
     7 int table1[LEN];
     8 int table2[LEN];
     9 
    10 int main()
    11 {
    12     int n, m;
    13     while(scanf("%d %d", &n, &m) != EOF){
    14         memset(table1, 0, sizeof(table1));
    15         memset(table2, 0, sizeof(table2));
    16         int t = -1;
    17         for(int i = 0; i < n; i++){ //读入并记录m的位置
    18             scanf("%d", arr+i);
    19             if (arr[i] == m)
    20                 t = i;
    21         }
    22         int ans = 0;
    23         if (t != -1)  //如果m不在序列中则ans = 0 否则为1,即只有他本身时的情况
    24             ans = 1;
    25         int ma = 0;
    26         int mi = 0;
    27         for(int i = t-1; i >= 0; i--){
    28             if (arr[i] < arr[t])
    29                 mi++;
    30             else
    31                 ma++;
    32             int tmp = ma - mi;  //哈希记录tmp。
    33             if (tmp < 0)
    34                 table1[-tmp]++;
    35             else
    36                 table2[tmp]++;
    37             if (ma == mi)  //特判t = 0的情况
    38                 ans++;
    39         }
    40 
    41         ma = 0;
    42         mi = 0;
    43         for(int i = t+1; i < n; i++){
    44             if (arr[i] < arr[t])
    45                 mi++;
    46             else
    47                 ma++;
    48             int tmp = mi - ma;
    49             if (tmp < 0)
    50                 ans += table1[-tmp];  //查询有没有出现过,若有,则加上出现的次数
    51             else
    52                 ans += table2[tmp];
    53             if (ma == mi) //特判t = 0
    54                 ans++;
    55         }
    56         printf("%d\n", ans);
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    USACO07FEB银牛派对
    求环总结
    NOIP2015信息传递(拓扑排序 / 并查集)
    APIO2012dispatching (左偏树)
    [编程题]山寨金闪闪 (面试题)
    【小米oj】简单直接全排列
    【小米oj】寻找归一数字
    【小米oj】dreamstart 的催促
    【小米oj】打羽毛球的小爱同学
    【小米oj】石头收藏家
  • 原文地址:https://www.cnblogs.com/kevince/p/3890442.html
Copyright © 2011-2022 走看看