这是一道贪心题

刚开始yy出来一个比较\(sb\)的贪心

之后发现它错了

首先这道题得先把题面翻译成人话

  1. 如果存在一个单词是它的后缀,且当前没被填入,代价为\(n*n\);

  2. 如果不存在一个单词是它的后缀,代价为\(x\);

  3. 如果存在一个单词是它的后缀,且已填入的是它后缀的单词中序号最大的为\(y\),代价为\(x-y\)。

显然如果出现了第一种情况那肯定就凉了,这个花费太大了

显然这是可以避免的,我们在插入一个串之前就必须把它的所有后缀插入

所以这里就需要\(Trie\)树了,我们将所有的串倒着插入\(Trie\)树,之后\(Trie\)树就可以处理后缀了

那之后呢,我们在原来的\(Trie\)上贪心吗

不是的,我们应该在建立一个新图,在这个图上我们用一个点代表一个字符串,每个点的父亲是他的后缀

于是我们就得到了一棵新的树

之后贪心就好了,优先选择子树较小的

这是非常显然的

首先我们明确一点,就是一个子树内部的相对答案是不会变的,就是说在这个子树内部被选择的第一个点被选择的顺序是\(x\),那么答案一定会是\(x+val\),\(val\)是固定的一个数,也就是这个子树内部的最优策略

所以我们要尽量保证进入每一棵子树的\(x\)的和尽量的小,显然我们优先选择较小的可以做到这一点

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<bitset>
#define re register
#define mp std::make_pair
#define maxn 510005
struct E
{
int v,nxt;
}e[maxn<<1];
char S[maxn];
int n,cnt,tot;
long long ans;
std::bitset<maxn> f;
int son[maxn][26];
int sz[maxn];
int num,head[maxn],sum[maxn];
typedef std::pair<int,int> pii;
std::priority_queue<pii,std::vector<pii>,std::greater<pii> > q[maxn];
inline void add_edge(int x,int y)
{
e[++num].v=y;
e[num].nxt=head[x];
head[x]=num;
}
inline void ins()
{
scanf("%s",S+1);
int now=0;
int len=strlen(S+1);
for(re int i=len;i;--i)
{
if(!son[now][S[i]-'a']) son[now][S[i]-'a']=++cnt;
now=son[now][S[i]-'a'];
}
f[now]=1;
}
void build(int x,int pre)
{
for(re int i=0;i<26;i++)
if(son[x][i])
{
if(f[son[x][i]]) add_edge(pre,son[x][i]),build(son[x][i],son[x][i]);
else build(son[x][i],pre);
}
}
void dfs(int x)
{
sum[x]=1;
for(re int i=head[x];i;i=e[i].nxt)
{
dfs(e[i].v);
sum[x]+=sum[e[i].v];
q[x].push(mp(sum[e[i].v],e[i].v));
}
}
void last(int x,int pre)
{
while(!q[x].empty())
{
tot++;
ans+=tot-pre;
int mid=q[x].top().second;
last(mid,tot);
q[x].pop();
}
}
int main()
{
scanf("%d",&n);
for(re int i=1;i<=n;i++) ins();
build(0,0);
dfs(0);
last(0,0);
std::cout<<ans;
return 0;
}

【[SCOI2016]背单词】的更多相关文章

  1. BZOJ4567[Scoi2016]背单词

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

  2. P3294 [SCOI2016]背单词

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

  3. 4567: [Scoi2016]背单词

    4567: [Scoi2016]背单词 https://www.lydsy.com/JudgeOnline/problem.php?id=4567 题意: 题意看了好久,最后在其他人的博客里看懂了的. ...

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

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

  5. 【bzoj4567】[Scoi2016]背单词

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

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

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

  7. [SCOI2016]背单词 题解

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

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

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

  9. [SCOI2016]背单词

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

  10. bzoj 4567: [Scoi2016]背单词

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

随机推荐

  1. Grid控件

    Grid控件是WPF布局容器中功能最强大.最灵活的控件.Grid控件基本上能够完成其他WPF容器控件所能完成的功能,Microsoft建议大多数界面的布局都使用Grid控件来实现,因此默认情况下.vs ...

  2. MySQL (一)(未完成)

    并发控制 读写锁 读锁: 共享锁 写锁: 排它锁 颗粒度 表锁,MySQL中开销最小的锁 行锁,MySQL中开销最大的锁 事务 ACID特性 原子性(Automatic) 隔离性(Isolation) ...

  3. spring mongodb增删改查操作

    添加数据 School @Id @GeneratedValue private long id; @Indexed(unique = true) private String name; studen ...

  4. async和await理解代码

    <1>:Async和Await的理解1 using System; using System.Collections.Generic; using System.Linq; using S ...

  5. java虚拟机的内存机制

    我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...

  6. visualvm 插件 visual gc 使用介绍

    visual gc 是 visualvm 中的图形化查看 gc 状况的插件. 具体详细介绍可参照: http://www.oracle.com/technetwork/java/visualgc-13 ...

  7. Max Sum(经典DP)

    求最长总和序列,状态转移方程:dp[i] = max(dp[i-1]+a[i].a[i]) 因为可能有负数,所以要判断dp是否大于0,如果小于0则序列中断,从中断点开始 起始点可以用数组s保存,有中断 ...

  8. No rabbit death problem

    package basic.java; /** * 不死神兔问题: * 有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,加入兔子都不死,问地二十个月的兔子对数 ...

  9. php判断网站收录情况

    php判断网站收录情况 <?php //检测网页是否被百度收录 function checkBaiduIndex($url){ $url='http://www.baidu.com/s?wd=' ...

  10. 【Python系列】Python包管理器pip

    缘起 这段时间忙着给朋友搞事,忙了好长一段时间,木有写博客很长时间了.之间做了两个东西,一个是邮件自动发送脚本,一个是数据处理软件.其中,在做数据处理软件的时候使用到了非Python系统库,是两个第三 ...