1. 程式人生 > >BZOJ1112: [POI2008]磚塊Klo(splay)

BZOJ1112: [POI2008]磚塊Klo(splay)

cst scrip 希望 n) != 倉庫 output new i++

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

解題思路:

主要是一個規律知道就好了:序列更改為中位數次數最小

證明嗎?

在實數範圍內,∑ |ai-v| 可以使用數形結合的方法轉化到數軸上,離散的值會更趨近於中點,也可以感性地理解一下,比較像杠桿。

好了廢話不多說。

相當於一個長度為k的yy出來的窗口在滑動,splay O(logn)維護中位數即可。

時間復雜度O(nlogn)

代碼:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6
#define ls ch[0] 7 #define rs ch[1] 8 #define inp tr[tr[root].ch[1]].ch[0] 9 using std::min; 10 using std::abs; 11 typedef long long lnt; 12 struct trnt{ 13 int ch[2]; 14 int fa; 15 int wgt; 16 int num; 17 lnt val; 18 lnt sum; 19 }tr[1000000],str; 20 int
n,k; 21 int root; 22 int top; 23 int siz; 24 int grv; 25 lnt ans; 26 lnt klo[1000000]; 27 int bin[1000000]; 28 bool whc(int spc) 29 { 30 return tr[tr[spc].fa].rs==spc; 31 } 32 void pushup(int spc) 33 { 34 tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+tr[spc].num; 35 tr[spc].sum=tr[spc].val*tr[spc].num+tr[lll].sum+tr[rrr].sum; 36 return ; 37 } 38 void rotate(int spc) 39 { 40 int f=tr[spc].fa; 41 bool k=whc(spc); 42 tr[f].ch[k]=tr[spc].ch[!k]; 43 tr[spc].ch[!k]=f; 44 tr[tr[f].fa].ch[whc(f)]=spc; 45 tr[spc].fa=tr[f].fa; 46 tr[f].fa=spc; 47 tr[tr[f].ch[k]].fa=f; 48 pushup(f); 49 pushup(spc); 50 return ; 51 } 52 void splay(int spc,int f) 53 { 54 while(tr[spc].fa!=f) 55 { 56 int ft=tr[spc].fa; 57 if(tr[ft].fa==f) 58 { 59 rotate(spc); 60 break; 61 } 62 if(whc(spc)^whc(ft)) 63 rotate(spc); 64 else 65 rotate(ft); 66 rotate(spc); 67 } 68 if(!f) 69 root=spc; 70 } 71 int place(int spc,int rnk) 72 { 73 if(tr[lll].wgt>=rnk) 74 return place(lll,rnk); 75 if(tr[spc].num+tr[lll].wgt>=rnk) 76 return spc; 77 return place(rrr,rnk-tr[spc].num-tr[lll].wgt); 78 } 79 int aa; 80 void maxmin(int spc,int v) 81 { 82 if(!spc) 83 return ; 84 if(tr[spc].val<v) 85 { 86 aa=spc; 87 return maxmin(rrr,v); 88 } 89 return maxmin(lll,v); 90 } 91 void minmax(int spc,int v) 92 { 93 if(!spc) 94 return ; 95 if(tr[spc].val>v) 96 { 97 aa=spc; 98 return minmax(lll,v); 99 } 100 return minmax(rrr,v); 101 } 102 void del(int &spc) 103 { 104 bin[++top]=spc; 105 tr[spc]=str; 106 spc=0; 107 return ; 108 } 109 int newp() 110 { 111 if(top) 112 return bin[top--]; 113 return ++siz; 114 } 115 void ins(int v) 116 { 117 aa=0; 118 maxmin(root,v); 119 splay(aa,0); 120 aa=0; 121 minmax(root,v); 122 splay(aa,root); 123 if(inp) 124 { 125 tr[inp].num++; 126 tr[inp].wgt++; 127 }else{ 128 inp=newp(); 129 tr[inp].fa=tr[root].rs; 130 tr[inp].num=tr[inp].wgt=1; 131 tr[inp].val=v; 132 } 133 pushup(inp); 134 pushup(tr[root].rs); 135 pushup(root); 136 return ; 137 } 138 void Del(int v) 139 { 140 aa=0; 141 maxmin(root,v); 142 splay(aa,0); 143 aa=0; 144 minmax(root,v); 145 splay(aa,root); 146 tr[inp].num--; 147 if(!tr[inp].num) 148 del(inp); 149 else 150 pushup(inp); 151 pushup(tr[root].rs); 152 pushup(root); 153 return ; 154 } 155 void update() 156 { 157 splay(1,0); 158 splay(2,1); 159 int x=place(inp,grv); 160 splay(x,2); 161 int spc=inp; 162 ans=min(ans,abs(tr[lll].sum-tr[lll].wgt*tr[inp].val)+abs(tr[rrr].sum-tr[rrr].wgt*tr[inp].val)); 163 return ; 164 } 165 int main() 166 { 167 root=1; 168 siz=2; 169 tr[root].val=-100; 170 tr[root].rs=2; 171 tr[2].val=0x3f3f3f3f3f3f3f3fll; 172 tr[2].fa=1; 173 scanf("%d%d",&n,&k); 174 grv=(k+1)>>1; 175 for(int i=1;i<=n;i++) 176 scanf("%lld",&klo[i]); 177 for(int i=1;i<=k;i++) 178 ins(klo[i]); 179 ans=0x7f7f7f7f7f7f7f7fll; 180 update(); 181 for(int i=k+1;i<=n;i++) 182 { 183 Del(klo[i-k]); 184 ins(klo[i]); 185 update(); 186 } 187 printf("%lld\n",ans); 188 return 0; 189 } 190

BZOJ1112: [POI2008]磚塊Klo(splay)