HDU 4908 BestCoder Sequence——BestCoder Round #3

本文介绍了一个有趣的问题:在给定1至N的排列中找出所有包含特定中位数M的最佳编码子序列。通过巧妙地转换问题,利用标记和计数技巧来解决这一挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BestCoder Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


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
 
/****************************************************/

出题人的解题思路:

将大于M的数标记为1,小于M的数标记为-1,M本身标记为0,则题目就是要求和为0并且包括M的连续序列的个数;用sum_i表示从第一个数到第i个数的标记的和,对于所有大于等于M的位置的i,我们要求小于M的位置的sum_j == sum_i的个数的和即为答案。

该题简单来说其实就是给你一个序列,里面是1~N的排列,问你其中以M为中位数的奇数长度的区间有多少个

刚开始没有理解median number的意思,以为M要在区间的正中间,看了Clarification之后才发现是中位数的意思。

而M要是一个区间内的中位数,需要满足的是该区间内比M大的数的个数与比M小的数的个数相等

那么我们可以记录M左右两边区间比M大的和比M小的差值的个数,再相乘。
要想做到这一点,可以先遍历M的左边,记录差值个数,而遍历右边时直接加上与左边差值一样的即可。

比如说记录包含M的区间中M左侧有多少个比M大的数或比M小的数,比M大的和比M小的可以抵消,记录净差值

若仍不明白,可以提出,我会给以回复,并对解题报告作出修正,谢谢

放上一组测试数据,以供参考

Input

7 4
1 5 4 2 6 3 7
Output
8

Hint
{4}
{1,5,4}
{5,4,2}
{4,2,6}
{1,5,4,2,6}
{4,2,6,3,7}
{5,4,2,6,3}
{1,5,4,2,6,3,7}

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
#define ll __int64
using namespace std;
const int N = 20005;
const int inf = 1000000000;
const int mod = 258280327;
int a[2*N],s[2*N];
int main()
{
    int n,m,i,k,j,ans;
    while(~scanf("%d%d",&n,&m))
    {
        memset(s,0,sizeof(s));
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==m)
                k=i;
        }
        for(i=k,j=0;i>=0;i--)
        {
            if(a[i]!=m)
                a[i]>m?j++:j--;
            s[N-j]++;
        }
        for(i=k,ans=j=0;i<n;i++)
        {
            if(a[i]!=m)
                a[i]>m?j++:j--;
            ans+=s[N+j];
        }
        printf("%d\n",ans);
    }
    return 0;
}
菜鸟成长记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值