BZOJ1112: [POI2008]砖块Klo(splay)
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
3
9
2
3
1
Sample Output
2
解题思路:
主要是一个规律知道就好了:序列更改为中位数次数最小
证明吗?
去问数竞的吧
好了废话不多说。
相当于一个长度为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