zoukankan      html  css  js  c++  java
  • [POI2008]KLO-Building blocks

    题目描述

    N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.你还要求输出结束状态时,每柱砖的高度。

    Solution

    这题相当于我们滑动一个大小为k的窗口,我们可以任意改动每摞砖的高度,那么最优高度为多少呢,很显然是中位数。

    所以这题变成了一道大水题,维护一个数据结构,支持插入,删除,查K大。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define N 100004
    using namespace std;
    int n,a[N],num[N<<2],k,top,jue;
    long long tr[N<<2],ans=0x7f7f7f7f,b[N],ansn;
    long long q(int cnt,int l,int r,int L,int R){
        if(L>R)return 0;
        if(l>=L&&r<=R)return tr[cnt];
        int mid=(l+r)>>1;
        long long ans=0;
        if(mid>=L)ans+=q(cnt<<1,l,mid,L,R);
        if(mid<R)ans+=q(cnt<<1|1,mid+1,r,L,R);
        return ans;
    }
    int qsum(int cnt,int l,int r,int L,int R){
        if(L>R)return 0;
        if(l>=L&&r<=R)return num[cnt];
        int mid=(l+r)>>1;
        int ans=0;
        if(mid>=L)ans+=qsum(cnt<<1,l,mid,L,R);
        if(mid<R)ans+=qsum(cnt<<1|1,mid+1,r,L,R);
        return ans;
    }
    void add(int cnt,int l,int r,int x,int tag){
        if(l==r){tr[cnt]+=b[x]*tag;num[cnt]+=tag;return;}
        int mid=(l+r)>>1;
        if(mid>=x)add(cnt<<1,l,mid,x,tag);
        else add(cnt<<1|1,mid+1,r,x,tag);
        tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
        num[cnt]=num[cnt<<1]+num[cnt<<1|1];
    }
    int find(int cnt,int l,int r,int k){
        if(l==r)return l;
        int mid=(l+r)>>1;
        if(num[cnt<<1]>=k)return find(cnt<<1,l,mid,k);
        else return find(cnt<<1|1,mid+1,r,k-num[cnt<<1]);
    }
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);
        top=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+top+1,a[i])-b;
        for(int i=1;i<=k;++i)add(1,1,top,a[i],1);
        ans=2e18;
        long long sum=(k+1)/2;
        for(int i=k;i<=n;++i){
            int x=find(1,1,top,sum);
            long long aa=b[x]*qsum(1,1,top,1,x-1)-q(1,1,top,1,x-1)+q(1,1,top,x+1,top)-b[x]*qsum(1,1,top,x+1,top);
            if(aa<ans){
                ans=aa;
                jue=i;
                ansn=b[x];
            }
            add(1,1,top,a[i+1],1);add(1,1,top,a[i-k+1],-1);
        }
        printf("%lld
    ",ans);
        for(int i=1;i<jue-k+1;++i)printf("%d
    ",b[a[i]]);
        for(int i=jue-k+1;i<=jue;++i)printf("%d
    ",ansn);
        for(int i=jue+1;i<=n;++i)printf("%d
    ",b[a[i]]);
        return 0;
    }
  • 相关阅读:
    vue项目中实现定时刷新页面(重新渲染数据实时更新)
    如何撤销 Git commit ?
    error: You have not concluded your merge (MERGE_HEAD exists)
    ajax的前世今生
    DevTools failed to load SourceMap: Could not load content for webpack:///node_modules/sockjs-client/
    Vue 项目如何配置代理解决跨域
    Nginx 到底是什么东西?
    JSON.parse()与JSON.stringify()的区别
    uni-app 中如何管理用户登录状态
    Oracle分析函数简析
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9664515.html
Copyright © 2011-2022 走看看