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

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

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

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

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

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

取$B=\sqrt{n\log n}$即可,总复杂度为$o(n\sqrt{n\log 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\n",ans[i]);
79 }

[cf700D]Huffman Coding on Segment的更多相关文章

  1. 【CodeForces】700 D. Huffman Coding on Segment 哈夫曼树+莫队+分块

    [题目]D. Huffman Coding on Segment [题意]给定n个数字,m次询问区间[l,r]的数字的哈夫曼编码总长.1<=n,m,ai<=10^5. [算法]哈夫曼树+莫 ...

  2. Codeforces 700D - Huffman Coding on Segment(莫队+根分)

    Codeforces 题目传送门 & 洛谷题目传送门 好家伙,刚拿到此题时我连啥是 huffman 编码都不知道 一种对 \(k\) 个字符进行的 huffman 编码的方案可以看作一个由 \ ...

  3. hdu 1053 (huffman coding, greedy algorithm, std::partition, std::priority_queue ) 分类: hdoj 2015-06-18 19:11 22人阅读 评论(0) 收藏

    huffman coding, greedy algorithm. std::priority_queue, std::partition, when i use the three commente ...

  4. [IR] Huffman Coding

    为了保证:Block中,所有的叶子在所有的中间结点的前面.Static: Huffman coding Dynamic: Adaptive Huffman 一些概念 压缩指标 • Compress a ...

  5. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  6. 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

    前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...

  7. <Sicily>Huffman coding

    一.题目描述 In computer science and information theory, a Huffman code is an optimal prefix code algorith ...

  8. 哈夫曼编码的理解(Huffman Coding)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...

  9. Huffman coding & Huffman tree

    Huffman coding & Huffman tree Huffman coding 哈夫曼编码 / 最优二元前缀码 Huffman tree 哈夫曼树 / 最优二叉树 https://w ...

随机推荐

  1. vite首次启动加载慢

    背景 随着vue3的到来,vite开始被各大vue3组件库使用,公司开始一个新项目,准备尝试用vite试一波. 问题发现 当把公司新项目移植到vite后,启动非常快,但发现页渲染时间慢了很多 可以看到 ...

  2. storm卡顿修改

    ​ 最近的webstorm越来越卡了,有时候甚至会弹出 Out of memory的窗口,提示要设置 xmx的值, 8G内存跑你这小软件还会不够用???要内存?给你,看你还会不会卡成翔! 于是果断给x ...

  3. uoj167 元旦老人与汉诺塔(记忆化搜索)

    QwQ太懒了,题目直接复制uoj的了 QwQ这个题可以说是十分玄学的一道题了 首先可以暴搜,就是\(dfs\)然后模拟每个过程是哪个柱子向哪个柱子移动 不多解释了,不过实现起来还是有一点点难度的 直接 ...

  4. Mysql双主双从高可用集群的搭建且与MyCat进行整合

    1.概述 老话说的好:瞻前顾后.患得患失只会让我们失败,下定决心,干就完了. 言归正传,之前我们聊了Mysql的一主一从读写分离集群的搭建,虽然一主一从或一主多从集群解决了并发读的问题,但由于主节点只 ...

  5. Visual Studio 重置窗口布局

    Visual Studio 重置窗口布局

  6. Java:ConcurrentHashMap类小记-3(JDK8)

    Java:ConcurrentHashMap类小记-3(JDK8) 结构说明 // 所有数据都存在table中, 只有当第一次插入时才会被加载,扩容时总是以2的倍数进行 transient volat ...

  7. 【Linux命令063】Linux非常简单常用的入门命令

    Linux常用命令 这是一篇我在公众号上发布的文章,还算较为受欢迎. 博客园这边荒废好长时间了,主要是最近一年经常撰写的文章都是Linux相关的入门文章. 不知道是否能通过博客园的首页审核. 1.cd ...

  8. UltraSoft - Beta - Scrum Meeting 12

    Date: May 28th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 会议记录修复了课程中心导入作业时出现重复的问题完成了消息中心界面的交互 Liuzh ...

  9. 微服务(三) Eureka注册中心和Ribbon负载均衡

    1. Eureka注册中心 1.1 Eureka的结构和作用 在上一篇文章中 微服务(二)服务拆分及远程调用 order-service在发起远程调用的时候,该如何得知user-service实例的i ...

  10. 力扣 - 剑指 Offer 57. 和为s的两个数字

    题目 剑指 Offer 57. 和为s的两个数字 思路1(哈希表) 这题首先想到的是使用两个for遍历,查找是哪两个相加等于target,但是时间复杂度确实\(O(N^2)\),时间复杂度太高,因此我 ...