我是靠谱客的博主 文静小丸子,最近开发中收集的这篇文章主要介绍CodeForces - 1005E1 Median on Segments (Permutations Edition)Median on Segments (Permutations Edition),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Median on Segments (Permutations Edition)

+传送门+


◇题意◇

给定一个长度为 n n 的序列,问在它的子序列中,有多少个满足该序列的中位数为m

注意:若序列长度为偶数则中位数为中间偏左
例如:在1 2 3 4 中的中位数为2


◇解析◇

中位数的性质

定义比中位数大的数为 A A ,比中位数小的数为B
在序列中 NumA=NumB N u m A = N u m B
在题目定义中还可以是 NumA=NumB+1 N u m A = N u m B + 1

基本想法

NumAlNumBl=NumBrNumAr N u m A l − N u m B l = N u m B r − N u m A r
即该段区间中
NumAl+NumAr=NumBl+NumBr N u m A l + N u m A r = N u m B l + N u m B r
同上
NumA=NumB N u m A = N u m B

再进一步

如何实现呢?
一个显然的想法,分别记录某一段区间内的
NumA N u m A NumB N u m B
自然,我们想到用前缀和记录
NumAi N u m A i NumBi N u m B i
但事实上我们需要记录的只有
deltaiNumAiNumBi d e l t a i ( N u m A i − N u m B i )
这里写图片描述
其中 delta[i]=A[i]B[i] d e l t a [ i ] = A [ i ] − B [ i ] delta[j]=A[j]B[j] d e l t a [ j ] = A [ j ] − B [ j ]
在序列 a[i...j] a [ i . . . j ] 中,若满足:
                A[j]A[i]=B[j]B[i] A [ j ] − A [ i ] = B [ j ] − B [ i ] (即 NumA[i...j] N u m A [ i . . . j ] == NumB[i...j] N u m B [ i . . . j ] )
——> delta[j]delta[i]=0 d e l t a [ j ] − d e l t a [ i ] = 0
——> delta[j]=delta[i] d e l t a [ j ] = d e l t a [ i ]
则序列 a[i...j] a [ i . . . j ] 为一满足 m m 为中位数的序列。

注意:
(1)A[], B[] B [ ] , delta[] d e l t a [ ] 都为前缀和
(2) a[i] a [ i ] , a[j] a [ j ] 分别在 m m 两侧

别把这个忘了

这里写图片描述


上图“注意”中:显然在此序列中不满足delta[j]=delta[i]
那我们再推一遍
                A[j]A[i]=B[j]B[i]+1 A [ j ] − A [ i ] = B [ j ] − B [ i ] + 1 (即 NumA[i...j] N u m A [ i . . . j ] == NumB[i...j]+1 N u m B [ i . . . j ] + 1 )
——> delta[j]delta[i]=1 d e l t a [ j ] − d e l t a [ i ] = 1
——> delta[j]1=delta[i] d e l t a [ j ] − 1 = d e l t a [ i ]


◇算法实现◇

显然,在上文思路中有几个关键的变量
delta[] d e l t a [ ] ,现在扫描到m的哪一侧( delta[i] d e l t a [ i ] delta[j] d e l t a [ j ] 分别在m两侧),m两侧分别可以配对的区间数即 delta d e l t a 相等的点数;

变量定义

因此,我们定义如下几个变量
(1) int i n t delta d e l t a
(为何不是数组?在求解过程中,我们需要统计的是 m m 两侧分别可以配对的区间数,及某两节点delta相等的数量,则我们只需记录m左侧值为 delta d e l t a 的点数,再在 m m 右侧用某时delta配对即可)
(2) bool b o o l flag f l a g
(现在扫描过m吗,即此刻是在m的左侧否)
(为何要记录?在(1)中已经解释了,m左边是统计,右边是配对)
(3) cnt[] c n t [ ]
(下标为 delta d e l t a ,记录delta为某一值的点数,方便在m右侧配对时统计数量)

算法流程

(1)在输入过程中维护 delta d e l t a flag f l a g (输入= m m ,)
flag=0 cnt[delta]++ c n t [ d e l t a ] + +
flag=1 f l a g = 1 ans+=cnt[delta]+cnt[delta1] a n s + = c n t [ d e l t a ] + c n t [ d e l t a − 1 ]
cnt[delta1] c n t [ d e l t a − 1 ] delta[j]1=delta[i] d e l t a [ j ] − 1 = d e l t a [ i ] 型的配对)
(2)很容易想到, delta d e l t a 极有可能在某一时刻为一负数,因此,我们将 cnt c n t 的坐标向右平移 MAXN M A X N 位,轻松的解决了这个简单的问题。


◇代码◇

/*Wiz*/
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=2*int(1e5);
int del;
int n,m;
int C[2*MAXN+5];
int main()
{
    int x;
    LL ans=0;
    bool f=0;
    C[MAXN]=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d",&x);
        if(x>m) del++;
        if(x<m) del--;
        if(x==m) f=1;
        if(f)
            ans+=C[del+MAXN]+C[del-1+MAXN];
        else C[del+MAXN]++;
    }
    printf("%lld",ans);
}
再说两句

这道题建议使用读入优化;
不是说不用很慢,过不了,但用了效率速度就很快了。
这里写图片描述


Thanks T h a n k s For F o r Reading! R e a d i n g !

最后

以上就是文静小丸子为你收集整理的CodeForces - 1005E1 Median on Segments (Permutations Edition)Median on Segments (Permutations Edition)的全部内容,希望文章能够帮你解决CodeForces - 1005E1 Median on Segments (Permutations Edition)Median on Segments (Permutations Edition)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部