• BZOJ1367 BOI2004Sequence(左偏树)


      首先考虑把bi和ai同时减i,问题变为非严格递增。显然如果a是一个递减序列,b序列所有数都取其中位数最优。于是划分原序列使得每一部分递减,然后考虑合并相邻两段。如果前一段的中位数<=后一段的中位数,显然各自b的取值不变就行了;否则将b的取值统一改为合并后序列的中位数。感性证明。

      于是用左偏树维护中位数即可。具体操作时并不需要每次加一段,而是加一个就可以了,维护每段较小的⌈len/2⌉个数的大根堆,合并时如果两段的长度都为奇数就弹出一个,否则不变。因为只加一个,不会出现本应成为中位数的数被丢掉的情况。

      (没认真学过左偏树,好像算距离时用左子树跑得也差不多快?不过应该能被hack吧

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 1000010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,a[N],b[N],top,root[N],size[N],cnt;
    ll ans;
    struct data{int l,r,x,d;
    }heap[N];
    int merge(int x,int y)
    {
        if (!x||!y) return x|y;
        if (heap[x].x<heap[y].x) swap(x,y);
        heap[x].r=merge(heap[x].r,y);
        if (heap[heap[x].l].d<heap[heap[x].r].d) swap(heap[x].l,heap[x].r);
        heap[x].d=heap[heap[x].r].d+1;
        return x;
    }
    void del(int &x){x=merge(heap[x].l,heap[x].r);}
    int newpoint(int x){heap[++cnt].x=x;return cnt;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj1367.in","r",stdin);
        freopen("bzoj1367.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) a[i]=read()-i;
        //for (int i=1;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
        for (int i=1;i<=n;i++)
        {
            size[++top]=1;root[top]=newpoint(a[i]);
            while (top>1&&heap[root[top]].x<heap[root[top-1]].x)
            {
                top--;
                root[top]=merge(root[top],root[top+1]);
                if ((size[top]&1)&&(size[top+1]&1)) del(root[top]);
                size[top]+=size[top+1];
            }
            //for (int j=1;j<=top;j++) cout<<size[j]<<' '<<heap[root[j]].x<<"  ";cout<<endl;
        }
        int x=0;
        for (int i=1;i<=top;i++)
            for (int j=1;j<=size[i];j++)
            b[++x]=heap[root[i]].x;
        for (int i=1;i<=n;i++) ans+=abs(a[i]-b[i]);
        cout<<ans<<endl;
        //for (int i=1;i<=n;i++) printf("%d ",b[i]+i);
        return 0;
    }
     
    

      

  • 相关阅读:
    Tomcat常设参数
    JSON
    Linux常用命令
    【Swagger2】【3】API注解详解,以及注解常用参数配置
    【实战问题】【13】报错springBoot-tk.mybatis.mapper.MapperException: 无法获取实体类com.xx.User对应的表名!
    【实战问题】【12】报错org.apache.commons.lang.exception.NestableRuntimeException
    【Java】【50】BeanUtils.copyProperties();只从源对象中拷贝自己为null的值
    【JS】【32】清空file文件域
    【MySQL】【7】AES_ENCRYPT()加密与AES_DECRYPT()解密
    【Swagger2】【2】SpringBoot整合Swagger2
  • 原文地址:https://www.cnblogs.com/Gloid/p/10293234.html
Copyright © 2020-2023  润新知