zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    C# 不用添加WebService引用,调用WebService方法
    贪心 & 动态规划
    trie树 讲解 (转载)
    poj 2151 Check the difficulty of problems (检查问题的难度)
    poj 2513 Colored Sticks 彩色棒
    poj1442 Black Box 栈和优先队列
    啦啦啦
    poj 1265 Area(pick定理)
    poj 2418 Hardwood Species (trie树)
    poj 1836 Alignment 排队
  • 原文地址:https://www.cnblogs.com/wang9897/p/9426536.html
Copyright © 2011-2022 走看看