• [cf700D]Huffman Coding on Segment


    令$tot_{i}$为区间$[l,r]$中满足$a_{j}=i$的$j$的个数,将所有非0的$tot_{i}$取出,得到可重集$S$

    显然,有以下贪心:不断取出$S$中最小的两个元素,删除这两个元素并加入这两个元素的和,直至$|S|=1$,每一次两个元素的和的和即为答案

    使用莫队可以在$o(nlog n)$的时间内得到$S$,但上述过程暴力的复杂度为$o(nlog n)$,无法通过

    设置阈值$B$,考虑将上述过程分为两部分——$S$中存在元素$le B$和$S$中所有元素都$>B$

    在第一个部分中,我们可以记录$le B$的每一个元素的个数,并根据奇偶性简单处理即可(特别的,若恰存在一个元素$le B$,可以看作所有元素都$>B$),复杂度为$o(B)$

    在第二个部分中,显然元素个数不超过$frac{n}{B}$,直接用上述过程即可,复杂度为$o(frac{nlog n}{B})$

    取$B=sqrt{nlog n}$即可,总复杂度为$o(nsqrt{nlog n})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define ll long long
     5 struct Query{
     6     int x,y,id;
     7 }q[N];
     8 multiset<ll>S,S0;
     9 int K,B,n,m,a[N],tot[N],sum[N],sum0[N];
    10 ll ans[N];
    11 bool cmp(Query x,Query y){
    12     return (x.x/K<y.x/K)||(x.x/K==y.x/K)&&(x.y<y.y);
    13 }
    14 void add_times(int x){
    15     if (x<=B)sum[x]++;
    16     else S.insert(x);
    17 }
    18 void dec_times(int x){
    19     if (x<=B)sum[x]--;
    20     else S.erase(S.find(x));
    21 }
    22 void update_val(int x,int p){
    23     dec_times(tot[x]);
    24     tot[x]+=p;
    25     add_times(tot[x]);
    26 }
    27 ll calc(){
    28     ll ans=0;
    29     S0=S;
    30     for(int i=1;i<=B;i++)sum0[i]=sum[i];
    31     int lst=0;
    32     for(int i=1;i<=B;i++){
    33         if (!sum[i])continue;
    34         if (lst){
    35             sum[i]--;
    36             add_times(lst+i);
    37             ans+=lst+i;
    38             lst=0;
    39         }
    40         ans+=1LL*(sum[i]/2)*(2*i);
    41         if (2*i<=B)sum[2*i]+=sum[i]/2;
    42         else{
    43             for(int j=1;j<=sum[i]/2;j++)S.insert(2*i);
    44         }
    45         if (sum[i]&1)lst=i;
    46     }
    47     if (lst)S.insert(lst);
    48     while (S.size()>1){
    49         int x=(*S.begin());
    50         S.erase(S.begin());
    51         int y=(*S.begin());
    52         S.erase(S.begin());
    53         ans+=x+y;
    54         S.insert(x+y);
    55     }
    56     S=S0;
    57     for(int i=1;i<=B;i++)sum[i]=sum0[i];
    58     return ans;
    59 }
    60 int main(){
    61     scanf("%d",&n);
    62     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    63     K=(int)sqrt(n),B=(int)sqrt(n*log2(n));
    64     scanf("%d",&m);
    65     for(int i=1;i<=m;i++){
    66         scanf("%d%d",&q[i].x,&q[i].y);
    67         q[i].id=i; 
    68     }
    69     sort(q+1,q+m+1,cmp);
    70     int x=1,y=0;
    71     for(int i=1;i<=m;i++){
    72         while (q[i].x<x)update_val(a[--x],1);
    73         while (y<q[i].y)update_val(a[++y],1);
    74         while (x<q[i].x)update_val(a[x++],-1);
    75         while (q[i].y<y)update_val(a[y--],-1);
    76         ans[q[i].id]=calc();
    77     }
    78     for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
    79 }
    View Code
  • 相关阅读:
    Codeforces Round #564(div2)
    714
    1471
    UVa 11134
    UVa 1152 -4 Values whose Sum is 0—[哈希表实现]
    UVa 1374
    UVA 1343
    UVa 12325
    Yet Another Number Sequence——[矩阵快速幂]
    River Hopscotch-[二分查找、贪心]
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14962997.html
Copyright © 2020-2023  润新知