题解 P3466 【[POI2008]KLO-Building blocks】

· · 题解

解法:FHQ_Treap

当然也不是裸的Treap QwQ

先行提醒:记得开longlong QwQ

根据题意,很想出步骤:

解法很多:对顶堆,线段树和平衡树……

这里讲讲单棵平衡树怎么做

CODE

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
const long long maxn=2e5+5,INF=0x7fffffffffffff;
long long a[maxn];
long long n,k;
long long l,r;
long long ans_mid,ans_l,ans_r,ans=INF;

struct Fhq_Treap
{
    long long l[maxn],r[maxn],sz[maxn],val[maxn],heap[maxn],sum[maxn];
    long long num,root,x,y,z;

    inline void update(long long pst) 
    {
        sz[pst]=sz[l[pst]]+sz[r[pst]]+1;
        sum[pst]=sum[l[pst]]+sum[r[pst]]+val[pst];
        return;
    }

    inline long long new_node(long long key) 
    {
        sz[++num]=1,sum[num]=val[num]=key,heap[num]=rand();
        return num;
    }

    inline void split(long long pst,long long key,long long &x,long long &y)
    {
        if(!pst)
        {
            x=y=0;
            return;
        }
        if(val[pst]<=key)
            x=pst,split(r[pst],key,r[pst],y);
        else 
            y=pst,split(l[pst],key,x,l[pst]);
        update(pst);
        return;
    }

    inline long long merge(long long x,long long y)
    {
        if(!x||!y)
            return x+y;
        if(heap[x]<heap[y])
        {
            r[x]=merge(r[x],y),update(x);
            return x;
        }   
        else
        {
            l[y]=merge(x,l[y]),update(y);
            return y;
        }   
    }

    inline long long kth(long long pst,long long rak)
    {
        if(rak<=sz[l[pst]])
            return kth(l[pst],rak);
        if(rak==sz[l[pst]]+1)
            return val[pst];
        return kth(r[pst],rak-sz[l[pst]]-1);
    }

    inline void add(long long key)
    {
        split(root,key,x,y);
        root=merge(x,merge(new_node(key),y));
        return;
    }

    inline void del(long long key)
    {
        split(root,key,x,z),split(x,key-1,x,y);
        y=merge(l[y],r[y]);
        root=merge(x,merge(y,z));
        return;
    }

    inline long long query(long long key)
    {
        split(root,key,x,z),split(x,key-1,x,y);
        long long sz1=sz[x],sz2=sz[z];
        long long ans1=sum[x],ans2=sum[z];
        root=merge(x,merge(y,z));
        long long l=sz1*key-ans1,r=ans2-sz2*key;
        return l+r;
    }

}FT;

signed main(void)
{
    scanf("%lld %lld",&n,&k);
    for(long long i=1;i<=n;i++)
        scanf("%lld",&a[i]);

    for(long long i=0;i<k;i++)
        FT.add(a[i]);

    l=0,r=k-1;
    for(long long i=k,mid;i<=n;i++)
    {
        l++,r++;
        FT.del(a[l-1]),FT.add(a[r]);
        if(k&1)
            mid=FT.kth(FT.root,(k>>1)+1);
        else
            mid=(FT.kth(FT.root,k>>1)+FT.kth(FT.root,(k>>1)+1))>>1;
        long long temp=FT.query(mid);
        if(temp<ans)
            ans=temp,ans_mid=mid,ans_l=l,ans_r=r;
    }

    printf("%lld\n",ans);
    for(long long i=1;i<ans_l;i++)
        printf("%lld\n",a[i]);
    for(long long i=ans_l;i<=ans_r;i++)
        printf("%lld\n",ans_mid);
    for(long long i=ans_r+1;i<=n;i++)
        printf("%lld\n",a[i]);

    return 0;
}

小广告:自己的模板库,有各种标准模板,想学什么都可以来看看呀qwq

专供神犇点击的链接