巧克力

题目描述

小\(T\)有\(N\)块巧克力, 每块巧克力上都有一句话(由小写英文字母组成,不含标点) 。现在每块巧克力都断成了若干截,更糟糕的是,有一些碎片丢失了 ,但是剩下的碎片之间的顺序是可以辨识的。

形式化地,我们用 一个只含小写字母和#的字符串来代表一块巧克力, 其中#表示该位置断开了,可能缺失了一段字符, 也可能没有。

例如: 如果我们用\(a\)#\(a\)来表示一块巧克力, 则原来它上面的话可能是\(aa\), 也可能是\(aaa\),\(aaczraa\)等等, 但不会是\(aab\)

小\(T\)有\(N\)块巧克力, 每块巧克力上都有一句话(由小写英文字母组成,不含标点) 。现在每块巧克力都断成了若干截,更糟糕的是,有一些碎片丢失了 ,但是剩下的碎片之间的顺序是可以辨识的。

形式化地,我们用 一个只含小写字母和#的字符串来代表一块巧克力, 其中#表示该位置断开了,可能缺失了一段字符, 也可能没有。

例如: 如果我们用\(a\)#\(a\)来表示一块巧克力, 则原来它上面的话可能是\(aa\), 也可能是\(aaa\),\(aaczraa\)等等, 但不会是\(aab\)

输入输出格式

输入数据

输入第一行, 一个正整数 \(N\)

接下来\(N\)行, 每行一个字符串 , 意义如题所述一个非负整数, 表示你给出的答案

输出格式:

一个非负整数, 表示你给出的答案

对于所有的数据:

\(2≤N≤500, 000\), 所有字符串 的总长不超过 \(1, 000, 000\)

对于每个子任务的特殊限制:

Subtask1(12pts) : 满足性质①

所有字符串 长度相等

Subtask2(20pts) : 满足性质①

Subtask3(23pts) : \(N≤1, 000\)

Subtask4(45pts) : 无特殊限制

性质①: 每个字符串包含恰好一个#,且这个#在字符串的开头。


感觉这个题出的非常好,考场上只拿了前两个Subtask,刚第二题去了(结果第二题还凉了)

其实第两个测试点就可以给出后面的启示了。

我们前两个测试点的字符倒着搞进字典树里,然后随便dfs一下统计就行了

观察手玩我们发现,如果两个字符串的前缀和后缀均有包含关系(这里的指一直到第一个“#”位置),那么它们两个可以搞

证明可以从递归构造的角度证明

我们把前缀和后缀分别搞进两棵字典树,就可以随便搞出\(N^2\)的算法了

(满足四个点两两是祖孙关系)

如何进一步优化复杂度呢?

我们考虑像第二步那样,\(dfs\)一棵树,然后随时统计另一颗树的贡献。

考虑我们现在做到第一棵树的点\(i\),这时候我们已经激活了\(i\)到根的在第二棵树上可能产生贡献的点了。

发现\(i\)在第二棵树上的点的子树已及它到根的那条链的点权产生了贡献

用两个树状数组维护这个过程,一个维护子树贡献。

另一个讨论链上的点对它的子树都有贡献,实际上是子树加,单点查,差分维护


Code:

#include <cstdio>
#define ls now<<1
#define rs now<<1|1
#include <cstring>
#include <vector>
#define ll long long
using namespace std;
const int N=1e6+10;
int ch[N<<1][26],tot=1,root[2]={0,1},n;
char c[N];
vector <int > to[N<<1];
ll ans,cnt[N<<1];
void in()
{
scanf("%s",c);
int len=strlen(c),now=root[0];
for(int i=0;i<len&&c[i]!='#';i++)
{
if(!ch[now][c[i]-'a']) ch[now][c[i]-'a']=++tot;
now=ch[now][c[i]-'a'];
}
++cnt[now];
int las=now;
now=root[1];
for(int i=len-1;i&&c[i]!='#';i--)
{
if(!ch[now][c[i]-'a']) ch[now][c[i]-'a']=++tot;
now=ch[now][c[i]-'a'];
}
++cnt[now];
to[las].push_back(now);
}
int siz[N<<1],dfn[N<<1];
int dfs_order(int now)
{
dfn[now]=++n;
siz[now]=1;
for(int i=0;i<26;i++)
if(ch[now][i])
siz[now]+=dfs_order(ch[now][i]);
return siz[now];
}
ll sum[2][N];
ll query(int typ,int pos)
{
ll x=0;
while(pos)
{
x+=sum[typ][pos];
pos-=pos&-pos;
}
return x;
}
void change(int typ,int pos,ll del)
{
while(pos<=n)
{
sum[typ][pos]+=del;
pos+=pos&-pos;
}
}
void dfs(int now)
{
for(int i=0;i<to[now].size();i++)
{
int num=to[now][i];
ans+=query(0,dfn[num]+siz[num]-1)-query(0,dfn[num]-1);
ans+=query(1,dfn[num]);
change(0,dfn[num],1);
change(1,dfn[num]+1,1);
change(1,dfn[num]+siz[num],-1);
}
for(int i=0;i<26;i++)
if(ch[now][i])
dfs(ch[now][i]);
for(int i=0;i<to[now].size();i++)
{
int num=to[now][i];
change(0,dfn[num],-1);
change(1,dfn[num]+1,-1);
change(1,dfn[num]+siz[num],1);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) in();
n=0;
siz[root[1]]=dfs_order(root[1]);
dfs(root[0]);
printf("%lld\n",ans);
return 0;
}

2018.8.14

安徽师大附中%你赛day2T3 巧克力 解题报告的更多相关文章

  1. 安徽师大附中%你赛day3T1 怜香惜玉 解题报告

    怜香惜玉 题意: 已知 \(f(x)=\frac{2 \times \sum_{(i,x)=1}^x i}{φ(x)}\) 先给定数据组数\(t\)和\(k\) 每组数据给出\(n\),求\(\sum ...

  2. 安徽师大附中%你赛day4T2 演讲解题报告

    演讲 题目背景: 众所周知,\(\mathrm{Zdrcl}\)是一名天天\(\mathrm{AK}\)的高水平选手. 作为一民长者,为了向大家讲述自己\(\mathrm{AK}\)的经验,他决定在一 ...

  3. 安徽师大附中%你赛day4T1 金字塔 解题报告

    金字塔 题目背景: \(Zdrcl\)带着妹子们来到了胡夫金字塔周边旅游, 发现这里正在进行一个有关金字塔的游戏 题目描述: 游戏规则如下: 1. 这里的金字塔是一个 \(N\) 阶的二维金字塔. 2 ...

  4. 安徽师大附中%你赛day9 T2 富 解题报告

    富 题目背景 出于某些原因, 苟先生在追杀富先生. 题目描述 富先生所在的地方是一个\(n\times m\)的网格,苟先生排出了他的狼狗大军,共有\(k\)条狗,第\(i\)条狗所在的位置为\((x ...

  5. 安徽师大附中%你赛day9 T3 贵 解题报告

    贵 问题描述 苟先生的狼狗大军没有追上富先生, 所以他把它们都解雇了, 决定去雇佣一些更好的狗, 不过狗可是很贵的.苟先生有 \(w\) 元钱, 有 \(n\) 条狗可以雇佣, 第 \(i\) 条狗有 ...

  6. 安徽师大附中%你赛day7 T2 乘积 解题报告

    乘积 题目背景 \(\mathrm{Smart}\) 最近在潜心研究数学, 他发现了一类很有趣的数字, 叫做无平方因子数. 也就是这一类数字不能够被任意一个质数的平方整除, 比如\(6\).\(7\) ...

  7. 安徽师大附中%你赛day6 T3 Hamsters [POI2010]CHO-Hamsters 解题报告

    [POI2010]CHO-Hamsters 题意: 给出n个互不包含的字符串,要求你求出一个最短的字符串S,使得这n个字符串在S中总共至少出现m次,问S最短是多少? 范围: \(1 \le n \le ...

  8. 安徽师大附中%你赛day5 T3 树上行走 解题报告

    树上行走 题目背景 \(\mathrm{Smart}\) 的脑洞非常大, 经常幻想出一些奇怪的东西. 题目描述 某一天,\(\mathrm{Smart}\) 幻想出了一棵没有边际的二叉树,脑补着在那棵 ...

  9. 模拟赛T2 交换 解题报告

    模拟赛T2 交换 解题报告 题目大意: 给定一个序列和若干个区间,每次从区间中选择两个数修改使字典序最小. \(n,m\) 同阶 \(10^6\) 2.1 算法 1 按照题意模拟,枚举交换位置并比较. ...

随机推荐

  1. 为什么不早点使用 Git...

    教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013739628770 ...

  2. 2.5 进程控制之wait函数

    一.绪论 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果 是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是 ...

  3. Java学习笔记八:Java的流程控制语句之循环语句

    Java的流程控制语句之循环语句 一:Java循环语句之while: 生活中,有些时候为了完成任务,需要重复的进行某些动作.如参加 10000 米长跑,需要绕 400 米的赛道反复的跑 25 圈.在 ...

  4. CentOs安装Mysql和配置初始密码

    mysql官网yum安装教程,地址:https://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/#repo-qg-yum-fresh-install ...

  5. Redis的RDB与AOF介绍(Redis DateBase与Append Only File)

    RedisRDB介绍(Redis DateBase) 在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里 一.是什么? Redis会 ...

  6. 数列分块入门 1 LOJ6277

    题目描述 给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,单点查值. 输入格式 第一行输入一个数字 n. 第二行输入 n 个数字,第 iii 个数字为 a​i​​,以空格隔开. 接下来输 ...

  7. SQL数据库 面试题

    一.sql理论题 1.触发器的作用? 答:触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的.它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化. ...

  8. 新版IdFTP解决中文乱码问题

    用XE10后开发FTP客户端,发现有中文乱码问题.这里也主要是编码的问题,在connect链接后,需要设置编码方可. 注意:  IndyTextEncoding_OSDefault;   该代码可能需 ...

  9. android中接入twitter进行第三方登录

    在应用中接入Twitter进行第三方登录时,开发人员遇到了一点问题,主要是概念有点混乱,这里把经验记录一下,帮助遇到同样问题的朋友. 一.注册应用并配置登录权限 这一步比较简单,就不多说了,直接去官网 ...

  10. Lambda表达式在Kotlin中怎样工作的:setOnClickListener的转换(KAD 18)

    作者:Antonio Leiva 时间:Mar 28, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin-android/ 虽然,我在其它文章讲过一点 ...