【HDU】4908 (杭电 BC #3 1002题)BestCoder Sequence ——哈希

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 }

 

转载于:https://www.cnblogs.com/kevince/p/3890442.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值