「POI 2005」SZA-Template 「失配树」「双向链表」「思维」

先来观察答案的几个强性质。

首先答案肯定是原串的一个\(\tt{border}\),也就是失配树上的一条链。

再进一步观察:比如说答案在原串出现的位置分别为\(p_1, p_2, p_3... p_k\)(不妨设其严格升序),那么一定有\(\max (p_i - p_{i-1}) \leq length(ans)\)。

你问我为什么?如果大于的话就接不上了啊...

然后我们发现,只要满足上面那两个条件,那这个串一定就是个合法串。于是我们把这套东西搬到失配树上:

  1. 这个串是n在树上的祖先
  2. 这个串在树上的子树里所有节点的max_gap \(\leq\) 这个串结尾的下标

问题就变成了怎么维护max_gap.

你发现这个东西维护最靠右边的1,最靠左边的1,答案就可以用线段树合并做到\(\mathcal{O(n log n)}\),但是发现空间有点爆炸。

于是发现,可选的串只在一条链上,所以可以先全加进去,然后再逐步删,就可以用线段树做到\(\mathcal{O(n log n)}\)时间,\(\mathcal{O(n)}\)空间了。

然后发现这根本不用线段树,因为是逐步删答案只会不断变大,双向链表就可以解决。所以复杂度是\(O(n)\)的。

原文地址:https://www.cnblogs.com/LiM-817/p/12343176.html

时间: 2024-08-06 16:48:33

「POI 2005」SZA-Template 「失配树」「双向链表」「思维」的相关文章

树的旋转「POI 2011」

[题目描述] 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有\(n\)个叶子节点,满足这些权值为\(1\dots n\)的一个排列).可以任意交换每个非叶子节点的左右孩子. 要求进行一系列交换,使得最终所有叶子节点的权值按照遍历序写出来,逆序对个数最少. [输入格式] 第一行n下面每行,一个数x 如果\(x=0\),表示这个节点非叶子节点,递归地向下读入其左孩子和右孩子的信息, 如果\(x\ne 0\),表示这个节点是叶子节点,权值为\(x\) [输出格式] 一行,

「CodePlus 2017 12 月赛」火锅盛宴(模拟+树状数组)

1A,拿来练手的好题 用一个优先队列按煮熟时间从小到大排序,被煮熟了就弹出来. 用n个vector维护每种食物的煮熟时间,显然是有序的. 用树状数组维护每种煮熟食物的数量. 每次操作前把优先队列里煮熟时间<=当前时间的弹出,BIT上+1. 每次0操作把食物塞进优先队列和vector 每次1操作先看看树状数组里有没有数,没有输出angry,有的话在树状数组上二分找到最小的数. 每次2操作先看看树状数组里有没有这一种数,有的话输出并-1,没有的话看看vector有没有,有的话输出时间差,没有的话输出

「 Luogu P2574 」 XOR的艺术——线段树

# 解题思路 这题不难,但是原谅我一开始的傻逼想法,一会儿再给大家透露透露. 先说怎么做这题. 显然对于 $0$ 和 $1$ 来说,异或无非也就只有两种变化 异或了奇数次,$0$ 就会变成 $1$,$1$ 就会变成 $0$. 异或了偶数次,$0$ 和 $1$ 都不变. 那只需要在下传标记的时候下传修改了几次就可以. 好,下面说说我那傻逼的操作.我在下传标记的时候没有给子节点的 sum 进行异或,而是只下传了标记,并且在回溯的时候没有更新父节点的 sum 值. 然后我成功的没过样例,然鹅这并不傻逼

「美国花好几亿造出太空圆珠笔后,发现苏联航天员用铅笔」的故事真实吗?

一直以来自己的误区,感觉我真是 naive 美国和苏联的宇航员最早都用铅笔书写.“飞梭太空笔”出现后,两国都放弃了铅笔而采用太空笔.并且,太空笔是Fisher Pen公司花费了200万美元自主研发的,与美国政府无关. 真实的历史是,NASA和苏联太空项目中,最早使用的都是木质铅笔.但在零重力的环境下,木屑.石墨粉以及橡皮使用后的碎屑都会变成细小的悬浮物,给宇航员的生活及设备的运作带来很大影响. 经过改进后,美国采用机械铅笔(mechanical pencil, 就是现在的自动笔),苏联则用油笔(

loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】

题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\)的概率 如果\(i\)是叶节点显然 如果\(i\)只有一个儿子直接继承即可 如果\(i\)有两个儿子,对于儿子\(x\),设另一个儿子为\(y\) 则有 \[f[i][j] += f[x][j](1 - p_i)\sum\limits_{k > j}f[r][k] + f[x][j]p_i\sum\

loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define bit bitset<B + 1> using namespace std; const int MAXN = 501, B = 1001, SS = 4001; inline int read() { char c = getchar

「UVA 11987」Almost Union-Find 「带权并查集」「思维」

你发现,这个第二个操作不可能用普通并查集来搞,很棘手 但是你考虑一下,并查集维护的是个森林结构,并且路径压缩的时候每个森林的根是不会变的, 也就是意味着每删掉一个点你需要让他的踪影消失匿迹即可,并不需要让他在原有的树结构上消失. 具体怎么消失?把贡献全在根上减掉即可,再新建一个新点连进去. 这个新点可以用id数组表示,即id[x]为x节点现在的编号. #include <bits/stdc++.h> #define test(...) fprintf(stderr, __VA_ARGS__)

BZOJ 1532 POI 2005 Kos-Dicing 最大流+二分

题目大意 给出一些比赛,每场比赛有一个人会胜出,问胜出最多次的人最少胜出多少次. 思路 首先二分答案,转化成判定问题.观察题目,注意到每场比赛只有一个人胜出,那么这可以成为网络流建图流量限制的依据. 具体: S->每个人 f:二分的最大胜出次数. 每个人->他参与的比赛 f:1 每场比赛->T f:1 每次判断最大流和比赛是否相等. CODE #define _CRT_SECURE_NO_WARNINGS #include <queue> #include <cstdi

[ POI 2005 ] Bank Notes

\(\\\) Description 给出 \(N\) 种货币的面值 \(b_i\) 和个数 \(c_i\) ,求最少需要用多少个硬币凑出 \(Q\) 元钱,并输出任意一种方案. \(n\le 200,Q,b_i ,c_i\le 2\times 10^4,\) 空间限制 64 M. \(\\\) Solution \(\\\) Code 原文地址:https://www.cnblogs.com/SGCollin/p/9898729.html