[POI2008] 砖块Klo

洛谷 P3466 传送门

bzoj 1112 传送门

用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 }
砖块
原文地址:https://www.cnblogs.com/eternhope/p/9669573.html