[bzoj4567][Scoi2016]背单词-Trie+贪心+模型转化
Brief Description
- 给你N个互不相同的字符串,记\(S_i\)为第i个字符串,现在要求你指定N个串的出现顺序,我们用\(V_i\)表示第i个字符串是第几个出现的,则V为1到N的一个排列。我们希望你指定的出现顺序可以使总代价最小
- 一个出现顺序的代价的计算方法如下依次考虑第i个串\(S_i\)对代价的贡献:
- 假如存在一个串\(S_j\), \(S_j\)为\(S_i\)的后缀:
- 假如存在一个串\(S_j\), \(S_j\)为\(S_i\)的后缀,且\(V_j>V_i\)则第i个串对代价的贡献为\(N\times N\)
- 否则,记\(P_i\)为所有满足\(S_j\)为\(S_i\)的后缀的j中\(V_j\)的最大值,第i个串对代价的贡献为\(V_i-P_i\)
- 否则,如果不存在一个串\(S_j\),使得\(S_j\)为\(S_i\)的后缀,则第i个串对代价的贡献为\(V_i\)
- 你需要输出这个最小的总代价.
- 假如存在一个串\(S_j\), \(S_j\)为\(S_i\)的后缀:
Algorithm Design
首先可以证明第一个条件是没有用处的.
然后我们视后缀为一种偏序关系, 那么字符串就构成了一颗树, 那么问题就转化成了给树上每个节点标号使得他的标号减去他的父亲的标号的和最小.
这是一个经典的贪心问题. 我们选择每次都选择最小的size子树进行标号, 不难证明这样做的correctness.
Code
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#define ll long long
#define pa std::pair<int, int>
const int maxn = 100000 + 100;
const int maxlen = 520000 + 100;
int n;
struct edge {
int to, next;
} e[maxn << 1];
char str[maxlen];
int rt = 1, sz = 1, ch[maxlen][26], len, id[maxlen], tot, head[maxn],
size[maxn], f[maxn], cnt, fa[maxn];
std::vector<pa> v[maxn << 1];
inline void ins(int id) {
int p = rt;
for (int i = len; i >= 1; i--) {
int x = str[i] - 'a';
if (!ch[p][x]) {
ch[p][x] = ++sz;
}
p = ch[p][x];
}
::id[p] = id;
}
inline void add_edge(int u, int v) {
e[++tot].to = v;
e[tot].next = head[u];
fa[v] = u;
head[u] = tot;
}
void dfs(int x, int fa) {
if (id[x]) {
add_edge(fa, id[x]);
fa = id[x];
}
for (int i = 0; i < 26; i++) {
if (ch[x][i])
dfs(ch[x][i], fa);
}
}
void dfs2(int x) {
size[x] = 1;
for (int i = head[x]; i; i = e[i].next) {
int y = e[i].to;
dfs2(y);
v[x].push_back(std::make_pair(size[y], y));
size[x] += size[y];
}
std::sort(v[x].begin(), v[x].end());
}
void getf(int x) {
if (x)
f[x] = ++cnt;
for (int i = 0; i < v[x].size(); i++)
getf(v[x][i].second);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", str + 1);
len = strlen(str + 1);
ins(i);
}
dfs(1, 0);
dfs2(0);
getf(0);
ll ans = 0;
for (int i = 1; i <= n; i++)
ans += f[i] - f[fa[i]];
printf("%lld", ans);
}
[bzoj4567][Scoi2016]背单词-Trie+贪心+模型转化的更多相关文章
- [BZOJ4567][SCOI2016]背单词(Trie+贪心)
1.题意表述十分难以理解,简单说就是:有n个单词,确定一个背的顺序,使总代价最小. 2.因为第(1)种情况的代价是n*n,这个代价比任何一种不出现第(1)种情况的方案都要大,所以最后肯定不会出现“背某 ...
- 【BZOJ4567】[Scoi2016]背单词 Trie树+贪心
[BZOJ4567][Scoi2016]背单词 Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他 ...
- BZOJ4567[Scoi2016]背单词
4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...
- [SCOI2016]背单词——trie树相关
题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...
- BZOJ4567 [Scoi2016]背单词 【trie树 + 贪心】
题目链接 BZOJ4567 题解 题意真是鬼畜= = 意思就是说我们应先将一个串的所有后缀都插入之后再插入这个串,产生代价为其到上一个后缀的距离 我们翻转一下串,转化为前缀,就可以建\(trie\)树 ...
- BZOJ4567 SCOI2016背单词(trie+贪心)
倒过来变成查询前缀.考虑怎么排序.第一条代价n*n就相当于inf,说明一个单词的所有前缀都要排在它前面.那么串的依赖关系就是trie的结构.二三条说明代价是Σidi-idfa,那么显然最后的编号应该是 ...
- [bzoj4567][Scoi2016][背单词] (贪心+trie树)
Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计 ...
- 2019.03.25 bzoj4567: [Scoi2016]背单词(trie+贪心)
传送门 题意: 给你n个字符串,不同的排列有不同的代价,代价按照如下方式计算(字符串s的位置为x): 1.排在s后面的字符串有s的后缀,则代价为n^2: 2.排在s前面的字符串有s的后缀,且没有排在s ...
- BZOJ 4567 [SCOI2016]背单词 (Trie树、贪心)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4567 题解: 显然答案一定小于\(n\times n\), 字符串倒过来变成前缀建Tr ...
随机推荐
- TCP系列06—连接管理—5、TCP fastopen(TFO)
一.TFO背景 当前web和web-like应用中一般都是在三次握手后开始数据传输,相比于UDP,多了一个RTT的时延,即使当前很多应用使用长连接来处理这种情况,但是仍然由一定比例的短连接,这额外多出 ...
- python 爬虫每天定时启动爬虫任务
# coding=utf-8 import datetime import time def doSth(): # 这里是执行爬虫的main程序 print '爬虫要开始运转了....' ...
- Go语言【第十篇】:Go数据结构之:指针
Go语言指针 Go语言中指针是很容易学习的,Go语言中使用指针可以更简单的执行一些任务.我们都知道变量是一种使用方便的占位符,用于引用计算机内存地址.Go语言的取地址符是 &,放到一个变量前使 ...
- [洛谷P5057][CQOI2006]简单题
题目大意:有一个长度为$n$的$01$串,两个操作: $1\;l\;r:$把区间$[l,r]$翻转($0->1,1->0$) $2\;p:$求第$p$位是什么 题解:维护前缀异或和,树状数 ...
- 【HUD-5790】Prefix (主席树+tire)
似乎是归队赛的最后一道题. 由于当时以为是公共字串所以没写555555,其实是求公共前缀. 做法是建立tire,把tire上的点编号看成是值,查询第l到第r个字符串的区间内不重复的值的个数.建立主席树 ...
- BZOJ2816:[ZJOI2012]网络——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2816 https://www.luogu.org/problemnew/show/P2173 有一 ...
- BZOJ4103 [Thu Summer Camp 2015]异或运算 【可持久化trie树】
题目链接 BZOJ4103 题解 一眼看过去是二维结构,实则未然需要树套树之类的数据结构 区域异或和,就一定是可持久化\(trie\)树 观察数据,\(m\)非常大,而\(n\)和\(p\)比较小,甚 ...
- 从零开始学Linux系统(三)安装CentOS-7及软件包管理操作
推荐博文: VirtualBox安装CentOS7步骤详解: https://my.oschina.net/AaronDMC/blog/840753 如何安装CentOS7字符界面 :http://b ...
- bzoj4552: [Tjoi2016&Heoi2016]排序(二分+线段树)
又是久违的1A哇... 好喵喵的题!二分a[p],把大于mid的数改为1,小于等于mid的数改为0,变成01串后就可以用线段树进行那一连串排序了,排序后如果p的位置上的数为0,说明答案比mid小,如果 ...
- javascript实用例子
js学习笔记,别错过!很有用的. /////////////////////////////////////////////////////////////////////////////////// ...