用treap维护一段长为k的区间即可。
先把1~k-1的都插入treap。
然后从k到n进行如下操作:
插入一个,计算,删除一个。
用到一个结论:最终的高度最优解一定是中位数,这个用反证法很容易证出来的。
然后就是裸的treap插入删除操作,加上一个求中位数。
bzoj1112不要求输出最终高度,删掉那行输出即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 8 int n,m,root,tot,a[100005]; 9 int s[100005][2],sz[100005],h[100005]; 10 int rk[100005],v[100005]; 11 ll sum[100005]; 12 13 void pushup(int p) 14 { 15 sz[p]=sz[s[p][0]]+sz[s[p][1]]+h[p]; 16 sum[p]=sum[s[p][0]]+sum[s[p][1]]+(ll)(v[p]*h[p]); 17 } 18 19 void lturn(int &p) 20 { 21 int son=s[p][1]; 22 s[p][1]=s[son][0]; 23 s[son][0]=p; 24 pushup(p); 25 pushup(son); 26 p=son; 27 } 28 29 void rturn(int &p) 30 { 31 int son=s[p][0]; 32 s[p][0]=s[son][1]; 33 s[son][1]=p; 34 pushup(p); 35 pushup(son); 36 p=son; 37 } 38 39 void ins(int &p,int val) 40 { 41 if(!p) 42 { 43 p=++tot; 44 v[p]=sum[p]=val; 45 h[p]=sz[p]=1; 46 rk[p]=rand(); 47 return; 48 } 49 sum[p]+=val,sz[p]++; 50 if(v[p]==val) 51 { 52 h[p]++; 53 return; 54 } 55 if(v[p]>val) 56 { 57 ins(s[p][0],val); 58 if(rk[s[p][0]]<rk[p])rturn(p); 59 }else 60 { 61 ins(s[p][1],val); 62 if(rk[s[p][1]]<rk[p])lturn(p); 63 } 64 } 65 66 void del(int &p,int val) 67 { 68 if(!p)return; 69 if(v[p]==val) 70 { 71 if(h[p]>1) 72 { 73 h[p]--,sz[p]--,sum[p]-=v[p]; 74 return; 75 } 76 if(s[p][0]*s[p][1]==0) 77 { 78 p=s[p][0]+s[p][1]; 79 return; 80 } 81 if(rk[s[p][0]]<rk[s[p][1]]) 82 { 83 rturn(p); 84 del(s[p][1],val); 85 }else 86 { 87 lturn(p); 88 del(s[p][0],val); 89 } 90 }else if(v[p]>val)del(s[p][0],val); 91 else del(s[p][1],val); 92 pushup(p); 93 } 94 95 int asz; 96 ll asum; 97 ll ans=(ll)(1e18); 98 int ap,amid; 99 100 int qnum(int p,int rank) 101 { 102 if(sz[s[p][0]]<rank&&sz[s[p][0]]+h[p]>=rank) 103 { 104 asz+=sz[s[p][0]],asum+=sum[s[p][0]]; 105 return v[p]; 106 } 107 if(sz[s[p][0]]>=rank)return qnum(s[p][0],rank); 108 else 109 { 110 asz+=(sz[s[p][0]]+h[p]); 111 asum+=(sum[s[p][0]]+(ll)(h[p]*v[p])); 112 return qnum(s[p][1],rank-(sz[s[p][0]]+h[p])); 113 } 114 } 115 116 int main() 117 { 118 scanf("%d%d",&n,&m); 119 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 120 rk[0]=(int)(1e9); 121 for(int i=1;i<m;i++)ins(root,a[i]); 122 for(int i=m;i<=n;i++) 123 { 124 ins(root,a[i]); 125 asz=0,asum=0; 126 int mid=qnum(root,(m+1)>>1); 127 ll nw=(ll)mid*asz-asum+sum[root]-asum-(ll)mid*(m-asz); 128 if(nw<ans)ans=nw,ap=i-m+1,amid=mid; 129 del(root,a[i-m+1]); 130 } 131 printf("%lld ",ans); 132 for(int i=1;i<=n;i++)printf("%d ",(i>=ap&&i<=ap+m-1)?amid:a[i]); 133 return 0; 134 }