[Bzoj1112][POI2008]砖块Klo(splay)

Posted lzdhydzzh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Bzoj1112][POI2008]砖块Klo(splay)相关的知识,希望对你有一定的参考价值。

1112: [POI2008]砖块Klo


 

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2353  Solved: 831
[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


 

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

 

 

分析:


splay求中位数。

 

 

AC代码:


 

# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const int N = 1e5 + 12;
LL s[N],ret = 1e18;int n,K,root,cnt;
struct node{
   int ch[2];
   int fa;
   int sz;LL val,sum;
   node(){}
   node(LL val):fa(0),sz(1),val(val),sum(sum){ch[0] = ch[1] = 0;}
}a[N];
void push(int x)
{
    a[x].sz = a[a[x].ch[0]].sz + a[a[x].ch[1]].sz + 1;
    a[x].sum = a[a[x].ch[0]].sum + a[a[x].ch[1]].sum + a[x].val;
}
void rotate(int now,int d)
{
    int pre = a[now].fa,g = a[pre].fa,nex = a[now].ch[d];
    a[pre].ch[d ^ 1] = nex;
    if(nex)a[nex].fa = pre;
    a[now].fa = g;
    if(g)a[g].ch[a[g].ch[1] == pre] = now;
    a[pre].fa = now;a[now].ch[d] = pre;
    push(pre);push(now);
}
void splay(int now)
{
    int pre,g;
    while(a[now].fa)
    {
        pre = a[now].fa,g = a[pre].fa;
        if(g && !((a[pre].ch[0] == now) ^ (a[g].ch[0] == pre)))rotate(pre,a[pre].ch[0] == now);
        rotate(now,a[pre].ch[0] == now);
    }
    root = now;
}
void insert(LL val)
{
    if(!root){a[++cnt] = node(val);root = cnt;return;}
    int now = root,pre;
    while(now)
    {
        pre = now;
        now = a[now].ch[val > a[now].val];
    }
    a[++cnt] = node(val);a[cnt].fa = pre;
    a[pre].ch[val > a[pre].val] = cnt;
    splay(cnt);
}
void erase(int now)
{
    splay(now);
    if(!a[now].ch[0] || !a[now].ch[1]){root = a[now].ch[0] + a[now].ch[1];}
    else
    {
        int p = a[now].ch[1];
        while(a[p].ch[0])p = a[p].ch[0];
        a[p].ch[0] = a[now].ch[0];
        a[a[now].ch[0]].fa = p;
        root = a[now].ch[1];a[root].fa = 0;
        splay(a[now].ch[0]);
    }
    a[root].fa = 0;
}
int find(int k)
{
    int now = root;
    while(k > 0)
    {
        if(a[a[now].ch[0]].sz < k){k -= a[a[now].ch[0]].sz;k--;if(k > 0)now = a[now].ch[1];}
        else now = a[now].ch[0];
    }
    return now;
}
int main()
{
  scanf("%d %d",&n,&K);
  for(int i = 1;i <= n;i++)scanf("%lld",&s[i]);
  for(int i = 1;i < K;i++)insert(s[i]);
  for(int i = K;i <= n;i++)
  {
      if(i - K)erase(i - K);
      insert(s[i]);
      int now = find((K + 1) >> 1);
      splay(now);
      LL s1 = a[a[now].ch[0]].sz,s2 = a[a[now].ch[1]].sz;
      LL pre = a[a[now].ch[0]].sum,bef = a[a[now].ch[1]].sum;
      if(s1 * a[now].val - pre + bef - s2 * a[now].val < ret)ret = s1 * a[now].val - pre + bef - s2 * a[now].val;
  }
  printf("%lld\n",ret);
}

 

以上是关于[Bzoj1112][POI2008]砖块Klo(splay)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1112 POI2008 砖块Klo

[BZOJ1112][POI2008]砖块Klo

BZOJ1112: [POI2008]砖块Klo

BZOJ1112: [POI2008]砖块Klo

BZOJ1112 - [POI2008]砖块Klo

bzoj1112[POI2008]砖块Klo Treap