题目大意:

  给出总长度不超过1E+5的不重复字符串集,给每个字符串选一个前缀使得可以区分它。

题目分析:

  KAN出的DIV2难度一般不高,想升Ranting的可以试试。

  简单的树上启发式合并,建出Trie树,一开始每个字符串用自己表示,每次向上合并的时候选出堆中最大元素变成当前位置,特判一下有end的地方即可。

  证明也很简单,我们考虑一个根没被选的子树,若我们要使得这个子树的代价最小,那么我们一定要选择一个位置放到根上来,不难发现选择深度最大的点是会最小的。由于树的子结构的关系,这样向上归纳也是正确的。

代码:

  

 #include<bits/stdc++.h>
using namespace std; const int sigma = ; int n,num,len,root;
char str[];
struct trie{
int end,sz,nxt[];
}T[]; int Num(char ch){return ch-'a';} void insert(int now,int pla){
if(pla == len) {T[now].sz++;T[now].end=;return;}
int um = Num(str[pla]);
if(T[now].nxt[um]){
insert(T[now].nxt[um],pla+);
}else{
num++; T[now].nxt[um] = num;
insert(T[now].nxt[um],pla+);
}
} void dfs(int now){
for(int i=;i<sigma;i++)
if(T[now].nxt[i]) dfs(T[now].nxt[i]),T[now].sz+=T[T[now].nxt[i]].sz;
} void read(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%s",str);
len = strlen(str);
insert(root,);
}
dfs(root);
} int ans = ;
int bel[];
priority_queue<int,vector<int>,less<int> > q[]; int merge(int a,int b){
if(q[a].size()<q[b].size()){
while(!q[a].empty()){
int k = q[a].top();q[a].pop();
q[b].push(k);
}
return b;
}else{
while(!q[b].empty()){
int k = q[b].top();q[b].pop();
q[a].push(k);
}
return a;
}
} void dfs2(int now,int val){
int flag = false;
for(int i=;i<sigma;i++){
if(T[now].nxt[i]) flag=true,dfs2(T[now].nxt[i],val+);
}
if(!flag){bel[now]=++num;q[num].push(val);return;}
for(int i=;i<sigma;i++){
if(T[now].nxt[i]){
if(bel[now]){bel[now]=merge(bel[now],bel[T[now].nxt[i]]);}
else bel[now] = bel[T[now].nxt[i]];
}
}
if(T[now].end){
q[bel[now]].push(val);
}else{
q[bel[now]].pop();
q[bel[now]].push(val);
}
} void work(){
num = ;
for(int i=;i<sigma;i++){
if(!T[root].nxt[i]) continue;
dfs2(T[root].nxt[i],);
int hh = bel[T[root].nxt[i]];
while(!q[hh].empty()){
ans += q[hh].top();q[hh].pop();
}
}
printf("%d",ans);
} int main(){
read();
work();
return ;
}

Codeforces965E Short Code 【启发式合并】【堆】的更多相关文章

  1. Codeforces 965E Short Code 启发式合并 (看题解)

    Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...

  2. BZOJ4919:[Lydsy1706月赛]大根堆(set启发式合并)

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

  3. UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】

    题目分析: 好像跑得很快,似乎我是第一个启发式合并的. 把玩具看成区间.首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间. 现在 ...

  4. P5290 [十二省联考2019]春节十二响(堆+启发式合并)

    P5290 [十二省联考2019]春节十二响 从特殊到一般 我们先看链的情况. 我们把点$1$左右的两条子链分别扔入堆里 每次取出两个堆的最大值,把答案累加上更大的那个(另一堆为空则直接加上去). 那 ...

  5. bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS

    4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 599  Solved: 260[Submit][Stat ...

  6. CF827D Best Edge Weight[最小生成树+树剖/LCT/(可并堆/set启发式合并+倍增)]

    题意:一张图求每条边边权最多改成多少可以让所有MST都包含这条边. 这题还是要考察Kruskal的贪心过程. 先跑一棵MST出来.然后考虑每条边. 如果他是非树边,要让他Kruskal的时候被选入,必 ...

  7. BZOJ4919 [Lydsy1706月赛]大根堆 【dp + 启发式合并】

    题目链接 BZOJ4919 题解 链上的\(LIS\)维护一个数组\(f[i]\)表示长度为\(i\)的\(LIS\)最小的结尾大小 我们可以用\(multiset\)来维护这个数组,子树互不影响,启 ...

  8. BZOJ.4919.[Lydsy1706月赛]大根堆(线段树合并/启发式合并)

    题目链接 考虑树退化为链的情况,就是求一个最长(严格)上升子序列. 对于树,不同子树间是互不影响的.仿照序列上的LIS,对每个点x维护一个状态集合,即合并其子节点后的集合,然后用val[x]替换掉第一 ...

  9. BZOJ4919 大根堆(动态规划+treap+启发式合并)

    一个显然的dp是设f[i][j]为i子树内权值<=j时的答案,则f[i][j]=Σf[son][j],f[i][a[i]]++,f[i][a[i]+1~n]对其取max.这样是可以线段树合并的, ...

随机推荐

  1. SkylineGlobe MFC C++ 开发示例代码

    SkylineGlobe的SDK底层是跨平台的C++内核,面向不同平台封装原生的API,具有很高的执行效率, 下面是C++二次开发时的示例代码: #import "D:\Program Fi ...

  2. Image Restoration[Deep Image Prior]

    0.背景 这篇论文是2017年11月29号第一次提交到arxiv并紧接着30号就提交了V2版本的. 近些年DCNN模型在图像生成和修复上面表现很好,大部分人认为好的原因主要是由于网络基于大量的图片训练 ...

  3. 通过重建清理SVN服务器无用目录,不丢失其他目录修改记录

    1.主要时有时间希望调整一些文件的目录结构,或者移除一个大量占用空间的文件节省服务器磁盘,但是又不希望调整后,对应的修改记录丢失.这时可以通过服务器目录重建实现. 2.重建后只是被排除掉的目录的修改记 ...

  4. Luogu3763 TJOI2017 DNA NTT/SA

    传送门 两种做法: ①SA 将两个串拼在一次建立后缀数组,把\(height\)数组求出来,然后对于\(S\)中每一个长度为\(T\)的串和\(T\)暴力匹配,每一次找到最长的\(LCP\)匹配,如果 ...

  5. BZOJ1185 HNOI2007 最小矩形覆盖 凸包、旋转卡壳

    传送门 首先,肯定只有凸包上的点会限制这个矩形,所以建立凸包. 然后可以知道,矩形上一定有一条边与凸包上的边重合,否则可以转一下使得它重合,答案会更小. 于是沿着凸包枚举这一条边,通过旋转卡壳找到离这 ...

  6. TopShelf 自动配置Service测试

    在开发中经常会遇到后台定时处理数据和任务的情况,处理这些事情大概有以下几种方案: 1.使用数据库的job功能.优点是在数据库中可以完成的就在数据库中完成,配置等基础设施数据库都提供,简单快捷.缺点是如 ...

  7. zookeepeer集群搭建

    一.预备工作 1.zookeepeer需要安装JDK,至于版本,大家可以去官网查询一下.这里我安装的是JDK8. 2.需要开放zookeepeer用到的端口,默认端口2181.2888.3888,至于 ...

  8. FFMPEG指令

    FFmpeg是一个用于音视频处理的自由软件,被广泛用于音视频开发.FFmpeg功能强大,本文主要介绍如何使用FFmpeg命令行工具进行简单的视频处理. 安装FFmpeg可以在官网下载各平台软件包或者静 ...

  9. linux RPM manager

    RPM manage:rpm2cpio package_name | cpio -id #将一个rpm包解压至当前目录rpm -qi package_name #查看一个已安装的rpm包信息rpm - ...

  10. springcloud 笔记

    官方教程 http://projects.spring.io/spring-cloud/ guide https://github.com/spring-guides 伪官方教程 https://sp ...