• BZOJ1112: [POI2008]砖块Klo


    题解: 一眼错误写法....拿平均数去当了标准  队友YY说可以中位数 然后我们可以通过主席树来维护区间第K大 以及小于他的和以及大于它的的和 然后窗口滑动取最小即可

    /**************************************************************
        Problem: 1112
        User: c20161007
        Language: C++
        Result: Accepted
        Time:3832 ms
        Memory:86056 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    const int MAXN=1e5+10;
    using namespace std;
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    vector<int>vec;
    typedef struct node{
        int l,r;ll sum;int num;
    }node;
    node d[MAXN*42];int rt[MAXN];
    int cnt;
    void built(int &x,int y,int l,int r,int t,ll vul){
        x=++cnt;d[x]=d[y];d[x].sum+=vul;d[x].num++;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)built(d[x].l,d[y].l,l,mid,t,vul);
        else built(d[x].r,d[y].r,mid+1,r,t,vul);
    }
    ll ans;int ans1;
    void querty(int x,int y,int l,int r,int t){
        if(l==r){ans+=d[y].sum-d[x].sum;ans1+=d[y].num-d[x].num;return ;}
        int mid=(l+r)>>1;
        if(t>mid)ans+=(d[d[y].l].sum-d[d[x].l].sum),ans1+=d[d[y].l].num-d[d[x].l].num,querty(d[x].r,d[y].r,mid+1,r,t);
        else querty(d[x].l,d[y].l,l,mid,t);
    }
    int ans2;
    void querty1(int x,int y,int l,int r,int t){
        if(l==r){ans2=l;return ;}
        int mid=(l+r)>>1;
        if(d[d[y].l].num-d[d[x].l].num>=t)querty1(d[x].l,d[y].l,l,mid,t);
        else querty1(d[x].r,d[y].r,mid+1,r,t-(d[d[y].l].num-d[d[x].l].num));
    }
    int n,k;ll a[MAXN];
    ll sum[MAXN];
    int main(){
        n=read();k=read();
        for(int i=1;i<=n;i++)a[i]=read(),vec.push_back(a[i]),sum[i]=sum[i-1]+a[i];
       // for(int i=k;i<=n;i++)vec.push_back((ll)((sum[i]-sum[i-k])/k));
        sort(vec.begin(),vec.end());
        int sz=unique(vec.begin(),vec.end())-vec.begin();
        for(int i=1;i<=n;i++)a[i]=lower_bound(vec.begin(),vec.begin()+sz,a[i])-vec.begin()+1;
        for(int i=1;i<=n;i++)built(rt[i],rt[i-1],1,sz,a[i],vec[a[i]-1]);
        ll cnt=9e18;ll t2,t3;int t1,t4;int ans3;
        for(int i=k;i<=n;i++){
        //int t1=lower_bound(vec.begin(),vec.begin()+sz,((sum[i]-sum[i-k])/k))-vec.begin()+1;
        if(k%2)querty1(rt[i-k],rt[i],1,sz,k/2+1),t1=vec[ans2-1];
        else querty1(rt[i-k],rt[i],1,sz,k/2),t1=vec[ans2-1],querty1(rt[i-k],rt[i],1,sz,k/2+1),t1+=vec[ans2-1],t1/=2;
    //  cout<<t1<<endl;
        ans3=t1;
        t4=lower_bound(vec.begin(),vec.begin()+sz,t1)-vec.begin()+1;
        if(vec[t4-1]!=t1)t4--;
        t1=t4;
        ans=0;
        //cout<<(sum[i]-sum[i-k])/k<<endl;
        ans1=0;
        querty(rt[i-k],rt[i],1,sz,t1);
    //  cout<<ans<<" "<<ans1<<endl;
        t2=1ll*ans1*ans3-ans;
        t3=sum[i]-sum[i-k]-ans;
        ans1=k-ans1;
        t3-=1ll*ans1*ans3;
        cnt=min(cnt,t2+t3);
        }
        printf("%lld
    ",cnt);
        return 0;
    }
    

    1112: [POI2008]砖块Klo

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2479  Solved: 883
    [Submit][Status][Discuss]

    Description

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

    Input

    第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000

    Output

    最小的动作次数

    Sample Input

    5 3
    3
    9
    2
    3
    1

    Sample Output

    2

    HINT

    原题还要求输出结束状态时,每柱砖的高度.本题略去.

  • 相关阅读:
    BOM和DOM
    前端CSS
    前端HTML
    索引 创建用户和授权 锁 事务
    多表查询 Naricat pymysql
    外键关联的修改 级联 修改表行记录的操作
    表的基础数据类型 MySQL的mod设置 表的约束
    数据库初识及操作命令
    LINUX 下LAMP之源码环境部署
    Nginx负载均衡配置实例详解【原】
  • 原文地址:https://www.cnblogs.com/wang9897/p/9426536.html
Copyright © 2020-2023  润新知