• bzoj 1367 [ Baltic 2004 ] sequence —— 左偏树


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1367

    好题啊!论文上的题;

    论文上只给出了不下降序列的求法:

    先考虑特殊情况,如果原序列上升,那么答案序列相同即可,如果下降,那么答案序列取中位数;

    那么对于跌宕起伏的原序列,可以先一个一个加入元素,每次加入一个作为一个新区间,中位数是自己;

    因为答案序列要不下降,所以当前区间的中位数比前一个区间大的时候就要合并,归纳可知(感性理解)整个区间的答案是它们的中位数;

    论文中有严谨证明:https://wenku.baidu.com/view/20e9ff18964bcf84b9d57ba1.html

    取中位数可以用一个大小是全体一半的大根堆,又要合并,所以就用可并堆;

    那么求上升序列呢?

    有个很巧妙的技巧,就是把原序列 t[i] = t[i] - i,然后对于这个序列求不下降序列;

    那么得到答案序列后,把答案序列的每个元素都 + i,就得到一个上升序列,而差值的和还是不变的。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const maxn=1e6+5;
    int n,t[maxn],l[maxn],r[maxn],rt[maxn],siz[maxn],num[maxn];
    int ls[maxn],rs[maxn],dis[maxn];
    ll ans;
    int abb(int x){return x>0?x:-x;}
    int merge(int x,int y)
    {
        if(!x||!y)return x+y;
        if(t[x]<t[y])swap(x,y);//维护大根堆 
        rs[x]=merge(rs[x],y);
        siz[x]=siz[ls[x]]+siz[rs[x]]+1;//+1
        if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
        if(rs[x])dis[x]=dis[rs[x]]+1;
        else dis[x]=0;
        return x;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&t[i]),t[i]-=i;
        int nw=0;
        for(int i=1;i<=n;i++)
        {
            l[++nw]=r[nw]=i; rt[nw]=i;
            siz[rt[nw]]=num[nw]=1;  
            while(nw>1&&t[rt[nw-1]]>t[rt[nw]])
            {
                nw--; 
                num[nw]+=num[nw+1]; r[nw]=r[nw+1];
                rt[nw]=merge(rt[nw],rt[nw+1]);
                while(siz[rt[nw]]*2>num[nw]+1)//+1
                    rt[nw]=merge(ls[rt[nw]],rs[rt[nw]]);
            }
        }
        for(int i=1;i<=nw;i++)
            for(int j=l[i];j<=r[i];j++)ans+=abb(t[j]-t[rt[i]]);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    DMA+USART重定义打印接口
    FTP初探
    ESP8266-lua开发
    GPIO常见问题分析
    新装系统简介
    java四个元注解的作用
    Linux常用操作指令
    @Autowired 与@Resource的区别(详细)
    内存溢出的几种原因和解决办法
    什么是NIO2
  • 原文地址:https://www.cnblogs.com/Zinn/p/9490395.html
Copyright © 2020-2023  润新知