BZOJ 1367 [Baltic2004]sequence 可并堆

题意:链接

方法:可并堆

解析:

wzc讲的第二道可并堆?不这是第一道,然后之前他好像还讲了个双堆求中位数?

大概想想,是不是就是维护一个小根堆以及一个大根堆,之后每次来元素,比中位数大就加到小根堆,比中位数小就加到大根堆,之后如果两堆差超过了2,就往少的里加,之后元素多的堆里的堆顶元素是新中位数?

好像是吧我也没太听,不过自己YY这感觉像是对的?

反正我不会写堆


以上与本题无关


接下来说本题:

首先让我们这么想,如果一个递增序列,那么它的对应选取的序列就是其本身,对答案没有贡献,如果一个递减序列,那么答案是什么呢?

是中位数。

证明请出门左转找数学竞赛的同志。

所有的元素,我们可以看做将其分为若干个线段,每一个线段都有一个中位数,最终将所有的答案加到一起就是结果。

然后具体怎么处理呢?

首先有一个新的元素来了,我们把它看做一个新的堆,之后呢,我们要观察这个堆与前面的堆有没有什么关系,如果当前这个堆的中位数的值比前一个堆的中位数的值要小,那么就不满足递增性质了,所以我们需要将这两个堆合并。

然后就处理完了,最后统计答案。

另外,对于这些中位数,我们维护出来的可能不满足严格递增,有可能是含不下降的,然而这个怎么处理呢?

听说是将a[i]-i,好像是这样?

这样是把不下降转为递增?

这里我写的是大根堆,好像小根堆也可以?

但是总感觉讨论的时候复杂啊。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1000100
using namespace std;
typedef long long ll;
int ch[N][2],key[N],size[N],root[N],h[N],L[N],R[N],w[N],num[N],a[N];
int n,m,x,tot,cnt;
void pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
int merge(int x,int y)
{
    if(!x)return y;
    if(!y)return x;
    if(key[x]<key[y])swap(x,y);
    ch[x][1]=merge(ch[x][1],y);
    pushup(x);
    if(h[ch[x][0]]<h[ch[x][1]])swap(ch[x][0],ch[x][1]);
    if(!h[ch[x][1]])h[x]=0;
    else h[x]=h[ch[x][1]]+1;
    return x;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]-=i;
    for(int i=1;i<=n;i++)
    {
        root[++tot]=++cnt;
        key[cnt]=a[i],size[cnt]=1;
        num[tot]=1,L[tot]=R[tot]=i;
        while(tot>1&&key[root[tot]]<key[root[tot-1]])
        {
            tot--;
            root[tot]=merge(root[tot],root[tot+1]);
            R[tot]=R[tot+1];
            num[tot]+=num[tot+1];
            while(size[root[tot]]>(num[tot]+1)/2)
            {
                root[tot]=merge(ch[root[tot]][0],ch[root[tot]][1]);
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=tot;i++)
    {
        for(int j=L[i];j<=R[i];j++)
        {
            ans+=abs(key[root[i]]-a[j]);
        }
    }
    printf("%lld\n",ans);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-22 13:00:08

BZOJ 1367 [Baltic2004]sequence 可并堆的相关文章

bzoj 1367: [Baltic2004]sequence(中位数+可并堆)

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 935  Solved: 351 [Submit][Status][Discuss] Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18. R=13 Source [Submit]

bzoj 1367: [Baltic2004]sequence

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MB Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18.R=13 详细证明请看IOI2005国家集训队论文  黄源河 https://wenku.baidu.com/view/20e9ff18964b

1367: [Baltic2004]sequence

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 1090  Solved: 432 [Submit][Status][Discuss] Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18. R=13 Source [题解]: 详

【bzoj1367】[Baltic2004]sequence 可并堆

题目描述 输入 输出 一个整数R 样例输入 7 9 4 8 20 14 15 18 样例输出 13 题解 可并堆,黄源河<左偏树的特点及其应用>Page 13例题原题 #include <cstdio> #include <cstring> #include <algorithm> #define N 1000010 using namespace std; int a[N] , root[N] , l[N] , r[N] , d[N] , w[N] , t

【BZOJ 1367】 [Baltic2004]sequence

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 631  Solved: 215 [Submit][Status] Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18. R=13 左偏树. 详细题解(在P13). 这个题解求的z

[BZOJ2809&amp;1455&amp;1367]解题报告|可并堆

其实非常好理解..就是可以可以合并起来的两个堆嘛>< 2809: [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送.现在你要招募一批忍者,并把它们派遣给顾客.你需要为每个被派遣的忍者 支付一

【BZOJ-1367】sequence 可并堆+中位数

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 932  Solved: 348[Submit][Status][Discuss] Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18.R=13 Source Solution 论文

【bzoj1367】[Baltic2004]sequence

2016-05-31 17:31:26 1 #include<bits/stdc++.h> 2 #define inf 1000000000 3 #define ll long long 4 #define N 1000005 5 using namespace std; 6 int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 wh

BZOJ 1367

1367: [Baltic2004]sequence Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1111  Solved: 439 [Submit][Status][Discuss] Description Input Output 一个整数R Sample Input 794820141518 Sample Output 13 HINT 所求的Z序列为6,7,8,13,14,15,18.R=13 学长论文:左偏树的特点及其应用 cnt是区间标