4567: [Scoi2016]背单词

https://www.lydsy.com/JudgeOnline/problem.php?id=4567

题意:

  题意看了好久,最后在其他人的博客里看懂了的。

  n个字符串,给它们排一个顺序。花费最小。对于第x个位置字符串的花费如下计算是这样的:

  • 如果存在它的一个后缀单词在它的后面,花费为x*x
  • 如果它的所有后缀单词都在它前面了,花费为x-last_pos(last_pos为它的后缀单词最后一个出现的位置,如果没有则为0)。

分析:

  贪心 + dfs序。

  首先第一个花费一定是不优的。那就是一个单词在它的所有的后缀单词的后面。

  然后反着建出trie树。把非单词结尾的节点去掉,然后形成一棵树。现在就是给这棵树编号,花费为所有的Σid[x]-id[fa[x]]。

  贪心的思路:优先给siz小的子树编号。

  理解一下:假设现在又两棵子树,第一棵子树的大小为a,另一棵为b,(a<b)。先给a编号后,子树b的根就是a+1,Ans+=(a+b)-id[fa],先给b编号,子树a的根为b+1,Ans+=(b+1)-id[fa]。然后子树内部的点的花费与父节点的差,所以不论父节点是多少,按照最优的情况编号,不变。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int ch[N][], dfn[N], siz[N], val[N], NowTime, Index;
char s[N];
vector<int> T[N];
LL Ans; void Insert(char *s,int n) {
int u = ;
for (int i=n; i>=; --i) {
int c = s[i] - 'a';
if (!ch[u][c]) ch[u][c] = ++Index;
u = ch[u][c];
}
val[u] = ;
}
void build(int u,int fa) {
if (val[u]) T[fa].push_back(u);
for (int i=; i<; ++i)
if (ch[u][i]) build(ch[u][i], val[u] ? u : fa);
}
bool cmp(int a,int b) {
return siz[a] < siz[b];
}
void dfs(int u,int fa) {
dfn[u] = ++NowTime;
if (u != ) Ans += dfn[u] - dfn[fa];
sort(T[u].begin(), T[u].end(), cmp);
for (int i=; i<T[u].size(); ++i) dfs(T[u][i], u);
}
int main() {
int n = read();
Index = ;
for (int i=; i<=n; ++i) {
scanf("%s",s + );
Insert(s, strlen(s + ));
}
build(, );
for (int i=Index; i>=; --i) {
if (!val[i]) continue;
siz[i] = ;
for (int j=; j<T[i].size(); ++j) siz[i] += siz[T[i][j]];
}
dfs(, );
cout << Ans;
return ;
}

4567: [Scoi2016]背单词的更多相关文章

  1. bzoj 4567: [Scoi2016]背单词

    Description Lweb 面对如山的英语单词,陷入了深深的沉思,"我怎么样才能快点学完,然后去玩三国杀呢?".这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册 ...

  2. BZOJ 4567 [SCOI2016]背单词 (Trie树、贪心)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4567 题解: 显然答案一定小于\(n\times n\), 字符串倒过来变成前缀建Tr ...

  3. BZOJ4567[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...

  4. 【bzoj4567】[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1123 Solved: 476[Submit][Status][ ...

  5. P3294 [SCOI2016]背单词

    P3294 [SCOI2016]背单词 Trie+贪心 倒插进树+取出重建+子树处理+贪心遍历 倒插进树:把后缀转化为前缀,所以把字符串倒着插进Trie中 取出重建:重新建立一棵以单词为节点的树,如果 ...

  6. 【BZOJ4567】[Scoi2016]背单词 Trie树+贪心

    [BZOJ4567][Scoi2016]背单词 Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他 ...

  7. [SCOI2016]背单词——trie树相关

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  8. [SCOI2016]背单词 题解

    背单词 https://www.luogu.com.cn/problem/P3294 前言: Trie树的省选题(瑟瑟发抖QAQ) 问题汇总:(请忽略) (1)对Trie字典树的运用不熟练 (2)没想 ...

  9. [BZOJ4567][SCOI2016]背单词(Trie+贪心)

    1.题意表述十分难以理解,简单说就是:有n个单词,确定一个背的顺序,使总代价最小. 2.因为第(1)种情况的代价是n*n,这个代价比任何一种不出现第(1)种情况的方案都要大,所以最后肯定不会出现“背某 ...

随机推荐

  1. note05-计算机网络

    5.网络安全 被动攻击(UDP报文被截获 被 进行流量分析) 主动攻击 1.篡改(更改报文流 伪报文) 2.恶意程序(病毒.木马.蠕虫.炸弹) 3.拒绝服务Dos 密码体制 1.对称密钥密码体制(DE ...

  2. MQ中将消息发送至远程队列的配置

    MQ中将消息发送至远程队列的配置 摘自MQ资源管理器帮助文档V7 在开始学习本教程之前,您需要从系统管理员处了解标识网络上接收机器的名称:IP地址.MQ的端口号.队列管理器.接收(远程机器)或者是发送 ...

  3. C++ 全局变量不明确与 using namespace std 冲突

    写了个汉诺塔,使用全局变量count来记录步数,结果Error:count不明确 #include <iostream> using namespace std; ; void hanoi ...

  4. PHP中使用substr()截取字符串出现中文乱码问题该怎么办

    一.使用mbstring扩展库的mb_substr()截取就不会出现乱码了. 可以用mb_substr()/mb_strcut()这个函数,mb_substr()/mb_strcut()的用法与sub ...

  5. shiro简单入门介绍

    shiro是apache的一个java安全框架 可以完成认证,授权,加密,会话管理,基于web继承,缓存等 功能简介: 从外部来看: shiro架构  Subject:主体,代表了当前“用户”,这个用 ...

  6. 关于Queue的相关问题

    在多线程中使用Queue,发现总是有莫名的问题, 经折腾好久之后发现是因为没有加锁! 以下测试代码中, 如果不加锁, 添加 100W对象, 可能只会成功50W, 然后并不会产生异常! );//(如果初 ...

  7. 【题解】洛谷P2023 [AHOI2009] 维护序列(线段树)

    洛谷P2023:https://www.luogu.org/problemnew/show/P2023 思路 需要2个Lazy-Tag 一个表示加的 一个表示乘的 需要先计算乘法 再计算加法 来自你谷 ...

  8. java 编写小工具 尝试 学习(二)

    1. 新建一个窗口  ,代码 如下 ,截图 如下 package jFrameDemo; import javax.swing.JFrame; import javax.swing.WindowCon ...

  9. write函数过程解析

    write函数作为用户向终端或者文件进行写数据的重要函数,有着重要的作用. |------|          |---------|   |---------| |----------| | wri ...

  10. 用javascript编写简单银行取钱存钱流程(函数)

    const readline = require('readline-sync')//引用readline-sync let arr = [[], []]; //登陆 let add = functi ...