• [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 }
    砖块
  • 相关阅读:
    python中join函数
    python实现反转字符串
    map函数
    python中lambda函数
    python中reduce函数
    python实现斐波那契数列
    迭代器和生成器
    经典算法动态图
    数据中心团队对于液体冷却的应用还需要适应
    物联网正将数据中心推向边缘
  • 原文地址:https://www.cnblogs.com/cervusy/p/9669573.html
Copyright © 2020-2023  润新知