• BZOJ1367: [Baltic2004]sequence(左偏树)


    Description

    Input

    Output

    一个整数R

    Sample Input

    7
    9
    4
    8
    20
    14
    15
    18

    Sample Output

    13

    解题思路:

    有趣的数学题。
    首先确定序列的构造方式。
    要求差的绝对值最小,并且递增。
    这肯定是照着A序列做的,那么很显然的结论:
    若A是递增的,那么Z一定是A序列。
    若A是平的,那么Z一定是公差为1的等差数列,中位数为A中的唯一值。
    那么就发现了,若保证其非减的话是非常容易得到最优解的。
    不断合并中位数即可,原理就是绝对值函数那个好几截棍。(数学课要好好听)
    合并中位数可以用可并堆,因为其定义为排名在中间的数,不是不断弹就好了。
    代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define lll l[x].ls
     5 #define rrr l[x].rs
     6 typedef long long lnt;
     7 struct lhnt{
     8     int ls;
     9     int rs;
    10     int fa;
    11     int dis;
    12     lnt val;
    13 }l[1000000];
    14 struct seg{
    15     int l;
    16     int r;
    17     int wgt;
    18     int root;
    19     lnt val;
    20     seg(){};
    21     seg(int x,lnt y)
    22     {
    23         l=r=root=x;
    24         wgt=1;
    25         val=y;
    26     }
    27 }st[1000000];
    28 int top;
    29 int n;
    30 lnt a[1000000];
    31 lnt b[1000000];
    32 int merge(int x,int y)
    33 {
    34     if(!x||!y)
    35         return x+y;
    36     if(l[x].val<l[y].val)
    37         std::swap(x,y);
    38     rrr=merge(rrr,y);
    39     l[rrr].fa=x;
    40     if(l[rrr].dis>l[lll].dis)
    41         std::swap(lll,rrr);
    42     l[x].dis=l[rrr].dis+1;
    43     return x;
    44 }
    45 int pop(int x)
    46 {
    47     return merge(lll,rrr);
    48 }
    49 int main()
    50 {
    51 //    freopen("a.in","r",stdin);
    52 //    freopen("my.out","w",stdout);
    53     scanf("%d",&n);
    54     for(int i=1;i<=n;i++)
    55     {
    56         scanf("%lld",&a[i]),a[i]-=i;
    57         st[++top]=seg(i,a[i]);
    58         l[i].val=a[i];
    59         while(top>1&&st[top].val<st[top-1].val)
    60         {
    61             int x=top-1,y=top;
    62             top--;
    63             st[x].root=merge(st[x].root,st[y].root);
    64             st[x].wgt+=st[y].wgt;
    65             st[x].r=st[y].r;
    66             while(st[x].wgt>((st[x].r-st[x].l+2)/2))
    67             {
    68                 st[x].root=pop(st[x].root);
    69                 st[x].wgt--;
    70             }
    71             st[top].val=l[st[top].root].val;
    72         }
    73     }
    74     lnt ans=0;
    75     for(int i=1;i<=top;i++)
    76         for(int j=st[i].l;j<=st[i].r;j++)
    77         {
    78             b[j]=st[i].val;
    79             ans+=std::abs(a[j]-b[j]);
    80         }
    81     printf("%lld
    ",ans);
    82     return 0;
    83 }
     
  • 相关阅读:
    什么是MongoDb
    Python之人工智能:PyAudio 实现录音 自动化交互实现问答
    Python人工智能之初识接口
    cordova(安卓)(腾讯信鸽注册绑定与反绑定) 插件开发
    sencha touch 在安卓中横屏、竖屏切换 应用崩溃问题
    Sencha Touch 实战开发培训 电子书 基础篇
    wps 批量调整图片大小 宏
    使用 crosswalk-cordova 打包sencha touch 项目,再也不用担心安卓兼容问题!
    Sencha Cmd 5.0.1.231 是坑爹货
    sencha touch api 使用指南
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10239413.html
Copyright © 2020-2023  润新知