1112: [POI2008]砖块Klo

时间:2022-05-08
本文章向大家介绍1112: [POI2008]砖块Klo,主要内容包括1112: [POI2008]砖块Klo、Description、Input、Output、Sample Input、Sample Output、HINT、Source、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

1112: [POI2008]砖块Klo

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 1245  Solved: 426

[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

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

Source

题解:(呵呵呵我会说我逗到了用Splay做这题的地步么= =)

首先,看这道题,对于某个高度序列而言,很明显将所有高度都变为中位数代价最小

我觉得任何一个数竞党都该知道怎么样可以让下列式子值最小——

( sum_{i=1}^{N} left | x-x_i right | ) 其中,( x_1 leq x_2 leq x_3 ... leq x_N ) 显然,当N为奇数时, ( x=x_frac{N+1}{2} ) 当N为偶数时, ( x_frac{N}{2} leq x leq x_frac{N+2}{2} )

然后接下来讨论怎么实现——我们需要一棵平衡树,可以加入和删除值,可以查询指定排名的数位置(用来找中位数),还得可以快速求出当前序列中比中位数大的各个数之和,以及比它小的之和,这样子就很明显需要维护子树大小(用于排名),然后还得维护子树和,然后我为了偷懒就直接来了个splay,每次将中位数splay上来,然后两边的不就是我们要的两边和嘛,然后该怎么办怎么办,别的没了

  1 /**************************************************************
  2     Problem: 1112
  3     User: HansBug
  4     Language: Pascal
  5     Result: Accepted
  6     Time:6156 ms
  7     Memory:27636 kb
  8 ****************************************************************/
  9  
 10 var
 11    i,j,k,m,n,head:longint;
 12    l,ans:int64;
 13    lef,rig,b:array[0..1000000] of longint;
 14    a,c:array[0..1000000] of int64;
 15 procedure rt(var x:longint);inline;
 16           var f,l:longint;
 17           begin
 18                if (x=0) or (lef[x]=0) then exit;
 19                b[lef[x]]:=b[x];b[x]:=b[rig[lef[x]]]+b[rig[x]]+1;
 20                c[lef[x]]:=c[x];c[x]:=c[rig[lef[x]]]+c[rig[x]]+a[x];
 21                f:=x;l:=lef[x];
 22                lef[f]:=rig[l];
 23                rig[l]:=f;
 24                x:=l;
 25           end;
 26 procedure lt(var x:longint);inline;
 27           var f,r:longint;
 28           begin
 29                if (x=0) or (rig[x]=0) then exit;
 30                b[rig[x]]:=b[x];b[x]:=b[lef[rig[x]]]+b[lef[x]]+1;
 31                c[rig[x]]:=c[x];c[x]:=c[lef[rig[x]]]+c[lef[x]]+a[x];
 32                f:=x;r:=rig[x];
 33                rig[f]:=lef[r];
 34                lef[r]:=f;
 35                x:=r;
 36           end;
 37 procedure splay(var x:longint;y:longint);inline;
 38           begin
 39                if (x=0) or (y=0) then exit;
 40                if y=(b[lef[x]]+1) then exit;
 41                if y<(b[lef[x]]+1) then
 42                   begin
 43                        if (b[lef[lef[x]]]+1)=y then rt(x) else
 44                           if y<(b[lef[lef[x]]]+1) then
 45                              begin
 46                                   splay(lef[lef[x]],y);
 47                                   rt(x);rt(x);
 48                              end
 49                           else
 50                               begin
 51                                    splay(rig[lef[x]],y-b[lef[lef[x]]]-1);
 52                                    lt(lef[x]);rt(x);
 53                               end;
 54                   end
 55                else
 56                    begin
 57                         y:=y-1-b[lef[x]];
 58                         if y=(b[lef[rig[x]]]+1) then lt(x) else
 59                            if y<(b[lef[rig[x]]]+1) then
 60                               begin
 61                                    splay(lef[rig[x]],y);
 62                                    rt(rig[x]);lt(x);
 63                               end
 64                            else
 65                                begin
 66                                     splay(rig[rig[x]],y-1-b[lef[rig[x]]]);
 67                                     lt(x);lt(x);
 68                                end;
 69                    end;
 70           end;
 71 procedure ins(var x:longint;y:longint);inline;
 72           begin
 73                if x=0 then
 74                   begin
 75                        x:=y;
 76                        exit;
 77                   end;
 78                if a[y]<=a[x] then
 79                   begin
 80                        ins(lef[x],y);
 81                        c[x]:=c[lef[x]]+c[rig[x]]+a[x];
 82                        b[x]:=b[lef[x]]+b[rig[x]]+1;
 83                   end
 84                else
 85                    begin
 86                         ins(rig[x],y);
 87                         c[x]:=c[lef[x]]+c[rig[x]]+a[x];
 88                         b[x]:=b[lef[x]]+b[rig[x]]+1;
 89                    end;
 90           end;
 91 function getrank(x,y:longint):longint;inline;
 92          begin
 93               if x=0 then exit(-1);
 94               if a[x]=y then exit(b[lef[x]]+1);
 95               if y<a[x] then exit(getrank(lef[x],y)) else exit(b[lef[x]]+1+getrank(rig[x],y));
 96          end;
 97 procedure init(x:longint);inline;
 98           begin
 99                ins(head,x);
100                splay(head,random(b[head])+1);
101           end;
102 procedure kill(x:longint);inline;
103           begin
104                if x=1 then
105                   begin
106                        splay(head,2);
107                        dec(c[head],c[lef[head]]);
108                        dec(b[head]);
109                        lef[head]:=0;
110                   end
111                else if x=b[head] then
112                     begin
113                          splay(head,b[head]-1);
114                          dec(c[head],c[rig[head]]);
115                          dec(b[head]);
116                          rig[head]:=0;
117                     end
118                else begin
119                          splay(head,x+1);
120                          splay(lef[head],x-1);
121                          dec(c[head],c[rig[lef[head]]]);dec(b[head]);
122                          dec(c[lef[head]],c[rig[lef[head]]]);dec(b[lef[head]]);
123                          rig[lef[head]]:=0;
124                     end;
125           end;
126 begin
127      readln(n,m);randomize;
128      if m<=1 then
129         begin
130              writeln(0);
131              halt;
132         end;
133      for i:=1 to n do
134          begin
135               readln(a[i]);
136               c[i]:=a[i];b[i]:=1;
137               lef[i]:=0;rig[i]:=0;
138          end;
139      head:=0;ans:=maxlongint*maxlongint;
140      for i:=1 to m do init(i);
141      for i:=1 to n-m+1 do
142          begin
143               splay(head,(m+1) div 2);
144               l:=0;
145               if lef[head]<>0 then inc(l,a[head]*b[lef[head]]-c[lef[head]]);
146               if rig[head]<>0 then inc(l,c[rig[head]]-a[head]*b[rig[head]]);
147               if l<ans then ans:=l;
148               if i=(n-m+1) then break;
149               kill(getrank(head,a[i]));
150               init(i+m);
151          end;
152      writeln(ans);
153      readln;
154 end.