[POI2008] Brick Klo

Description
N-pillar bricks, it is hoped that there are consecutive K-pillars with the same height. You can choose the following two actions: 1: Take a brick from the top of a certain pillar brick, and don't throw it away. 2: Take a brick from the warehouse, Put it on another column. The warehouse is infinitely large. Now want to complete the task with the minimum number of actions.

The first line of Input
gives N, K. (1 ≤ k ≤ n ≤ 100000), the following N lines, each line represents the height of the brick. 0 ≤ hi ≤ 1000000

Output
minimum number of actions

Sample Input
5 3
3
9
2
3
1

Sample Output
2

First of all, let me briefly talk about the meaning of the question, because I have been pitted...
There are n pillars, each time you can give a pillar height +1 or -1, use the least number of steps to make k consecutive pillars the same height

First of all, let's consider the k segments, what is the optimal height for these k pillars? Yes, the median.

So let's create a data structure that can maintain the median of the interval. Remember to find the sum of the previous smaller than the median and the latter larger than the median, and the statistical answer needs to be

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x>=10)     print(x/10);
    putchar(x%10+'0');
}
const int N=1e5;
ll Ans=1e18;
int V,L,R;
struct Splay{
    #define ls(x) tree[x][0]
    #define rs(x) tree[x][1]
    #define T(x) (rs(f[x])==x)
    int tree[N+10][2],f[N+10],size[N+10],v[N+10],root,len;
    ll sum[N+10];
    void clear(int x){size[x]=ls(x)=rs(x)=f[x]=sum[x]=v[x]=0;}
    void updata(int x){
        size[x]=size[ls(x)]+size[rs(x)]+1;
        sum[x]=sum[ls(x)]+sum[rs(x)]+v[x];
    }
    void move(int x){
        int fa=f[x],son=tree[x][T(x)^1];
        tree[x][T(x)^1]=fa;
        tree[fa][T(x)]=son;
        if (son)    f[son]=fa;
        f[x]=f[fa];
        if (f[x])   tree[f[x]][T(fa)]=x;
        f[fa]=x;
        updata(fa),updata(x);
    }
    void splay(int x){
        while (f[x]){
            if (f[f[x]])    T(x)==T(f[x])?move(f[x]):move(x);
            move(x);
        }
        root=x;
    }
    void insert(int x){
        v[++len]=x;
        if (!root){
            size[root=len]=1;
            return;
        }
        int i=root;
        while (true){
            size[i]++,sum[i]+=x;
            if (x<=v[i]){
                if (!ls(i)){f[ls(i)=len]=i;break;}
                i=ls(i);
            }else{
                if (!rs(i)){f[rs(i)=len]=i;break;}
                i=rs(i);
            }
        }
        splay(len);
    }
    int get_pre(){
        int x=ls(root);
        while (rs(x))   x=rs(x);
        return x;
    }
    int get_suc(){
        int x=rs(root);
        while (ls(x))   x=ls(x);
        return x;
    }
    int find(int i,int x){
        if (!i) return 0;
        if (x==size[ls(i)]+1)   return i;
        if (x<=size[ls(i)]) return find(ls(i),x);
        return find(rs(i),x-size[ls(i)]-1);
    }
    bool work(int k){
        splay(find(root,(k+1)>>1));
        ll res=size[ls(root)]*v[root]-sum[ls(root)]+sum[rs(root)]-size[rs(root)]*v[root];
        if (Ans>res){
            Ans=res,V=v[root];
            return 1;
        }
        return 0;
    }
    void Delete(int x){
        splay(x);
        if (!(ls(x)&&rs(x))){
            f[root=ls(x)+rs(x)]=0;
            clear(x);
            return;
        }
        int i=get_pre();
        splay(i);
        f[rs(i)=rs(x)]=i;
        clear(x);
        updata(root);
    }
    int get_rank(int x){
        int res=0;
        for (int i=root;i;){
            if (x<=v[i])    i=ls(i);
            else    res+=size[ls(i)]+1,i=rs(i);
        }
        return res+1;
    }
    void Del(int x){Delete(find(root,get_rank(x)));}
}T;
int val[N+10];
int main(){
    int n=read(),k=read();
    for (int i=1;i<=n;i++)  val[i]=read();
    for (int i=1;i<=k;i++)  T.insert(val[i]);
    for (int i=k+1;i<=n;i++){
        if (T.work(k))  L=i-k,R=i-1;
        T.Del(val[i-k]);
        T.insert(val[i]);
    }
    if (T.work(k))  L=n-k+1,R=n;
    printf("%lld\n",Ans);
//  for (int i=1;i<=n;i++)  printf("%d\n",(L<=i&&i<=R)?V:val[i]);
//原题要输出最后的状态,bzoj不用,故选择性注释掉
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324894668&siteId=291194637