thuwc2020

Day1

A

有一个长度为 \(k\) 的序列 \(a\),接下来有 \(m\) 次操作,每次操作给出一个新的长度是 \(k\) 的序列 \(b\)\(p_i\),如果 \(a_{p_i}<b_{p_i}\) 那么把 \(b\) 赋值到 \(a\) 上。

\(q\) 次询问,给出最初序列,问最后序列长啥样。

\(n,q\le 10^5,k\le 20\)

简单题。

最后的序列一定是给出的某个序列。并且最初的序列一旦被换过一次之后,最后被换成啥就确定下来了。

接下来唯一的问题是,给你一个序列,问之后第一个能把它换下来的是哪一个。

那显然,你可以枚举下一个把它换了的是哪个位置比它大,然后我们取最早的一个就行了。

B

给一张有向图,每个边有边权 \(w_i\) 表示这个边如果走了 \(w_i\) 次就会被删除。

接下来给 \(q\) 次互不独立的询问,每次给一个出发点 \(x\) 和一个步数上限 \(s\),棋子总会沿着编号最小的出边走,直到走了 \(s\) 步或者无路可走。每次询问要给出棋子的终点在哪。

\(n,q\le 10^5,m\le 1.5\times 10^5,s\le 10^9,w_i\le 10^{18}\)

只要没有边被删除,那它的移动方式我们是很清楚的,就是基环树。

而边的删除操作只会发生 \(m\) 次,所以我们相当于要维护 \(m\) 次删除操作。

问题变成,你有一个基环树森林,需要维护 \(m\) 次改边操作,以及 \(q\) 次询问从一个点开始跳 \(s\) 步能到哪。

这东西大概是可以用 lct 维护的,虽然这做法一点都不好。

观察到数据范围不大,可以尝试想一个根号做法。

根号重构是不是很有希望。你维护一个真实的 fa 指针,然后向上跳到第一个被修改过的地方,改跳真实的指针。如果这个地方之前已经被跳过一次了,说明我们找到了环,那接下来就是 repeat 若干次。否则说明每个地方至多被跳了一次,总之都是根号的。

额大概得是根号 log,常数还很大。但是 std 给 lct 的题真的没啥意思吧。

~ C

这个题不是 lxl 题吗。

给一棵树,以及一个常数 \(X\)

\(q\) 次询问,每次给一个区间 \([l,r]\)。我们定义两个点 \(u,v\) X-连通,当且仅当,\(l\le u,v\le r\),并且存在一条 \(u\to v\) 的路径,路上只经过 \([l,r]\) 内的点,路径上相邻两点在树上距离 \(\le X\)

每次询问问这样的 X-连通能形成多少个连通块。

\(n\le 3\times 10^5,q\le 6\times 10^5\)

虽然做过了但是我们还是来想一下。

如何统计每个 X-块,我们可以选择在树上最浅的点统计,如果有多个点,可以在 dfs 序最小的点统计。或者换句话说,我们统计 bfs 序最小的点。

你感受一下两个点 \(u,v\) 是怎么连起来的。然后你再感受一下,就会发现如果 \(u\) 想跟某个比自己 bfs 序小的点连通,就一定要跟比自己 bfs 序小的点有一个连边。

证明考虑如果没有连边,那你想跳过去就得先向下或者向右走,但是这些点到 bfs 序更小的点的距离不会变小,所以你这么跳是永远跳不到 bfs 序小的点的。

我们考虑怎样的 \([l,r]\) 满足 \(u\) 是被统计的点,发现这要求 \(u\) 跟 bfs 序小的点之间没有连边。这个你显然可以求一个 \(tol_u,tor_u\) 出来,然后就做完了。

Day2

* A

\(n\) 个函数 \(f(x)=a_i|x|+b_ix+c_i\) 以及初始值 \(s\),你可以打乱使用函数的顺序,要最后的结果最大。

\(n,|a_i|,|b_i|,|c_i|\le 15\)

烂完了。烂完了。烂完了。烂完了。烂完了。烂完了。

感觉,脑子非常不清醒,不知道自己在干什么。

首先要状压。如果你只记录最大最小值就似了,所以我们记录最大最小以及大于零最小小于零最大,然后你发现可以过 \(a=0\) 以及 \(c=0\) 的 sub。

考虑为什么这样会错。因为你关心大于零最小的一个,所以如果有一个函数,它的零点是 \(x_0,x_1\),那你还关心离 \(x_0/x_1\) 最近的一个。也就是说,你关心离 \([-15,15]\) 最近的一个。不断继续下去,你发现如果接下来还要复合上 \(n\) 个函数的话,那你关心你离 \([-15n,15n]\) 最近的一个,这个只需要维护 \([-15n,15n]\) 当中每个数是否出现,以及在这个范围两侧分别最大最小值就可以了。

总复杂度 \(O(2^nn^3)\)

这种东西就是分析细一点就能做出来,但是分析恰恰是我最烂的。但是哪个题不需要分析???

~ B

给一个 DAG,保证可以从 \(1\) 到达所有点。然后我们取出来以 \(1\) 为根的一个 dfs 生成树,定义树上的边为树边。

\(q\) 次询问,给定树上两点 \((a,b)\),保证 \(a\)\(b\) 的祖先,询问如果删除树上 \(a\to b\) 的链,\(b\) 子树中有多少个点无法从 \(1\) 到达。

\(n,q\le 10^5,m\le 1.5\times 10^5\)

首先,你给出一个 dfs 序,但是这个 dfs 序走的顺序跟你 dfs 的过程正好反过来。然后你发现所有连边都是从小的连向大的。

所以我们发现,你一个路径如果走到了 \(b\) 的子树里,就不会再走出去了。否则一定无法走回来。这样 \(b\) 子树当中只有若干个关键点是重要的。具体来说这些关键点是存在一条从外面连进来的路径的点。

上面这个关键点说了跟说了一样。我们定义关键点是删除 \(a\) 子树内所有树边之后,仍能够被到达的点。

我们关心的其实是 \((a,b,c)\) 这样的对,给你一个 \((a,b)\) 问有多少个在 \(b\) 内的 \(c\) 满足条件。

可能算看了一些 tip。

我们猜测,\(b\) 子树内的 \(c\) 能够被到达,当且仅当它有一个祖先是 \(a\) 时的关键点。

考虑反证法,我们先取出来所有 \(a\) 的关键点,然后假装有一个原来不可达的 \(c\),我们取一个最浅的,它在加上一些 \(a\) 子树内的树边之后,变得可达了。这就说明到 \(c\) 的路径一定要经过树边,就说明一定存在一个祖先也符合 \(c\) 的条件,与最浅矛盾,所以不存在。

因为是不是关键点显然具有单调性,所以我们想求出来每个点成为关键点的时刻。然后你发现这个时刻可以通过按 dfs 序倒序求出来。

让我先写个暴力看看我的结论对不对。

错了。

换一个定义。我们称 \(u\)\(a\) 时的关键点,当且仅当删除 \(a\to u\) 时能到达 \(u\)。我们声称,在 \((a,b)\) 条件下可以到达 \(b\) 子树内的 \(c\) 等价于 \(c\) 有一个祖先是关键点。

考虑反证,我们取出所有 \(a\) 的关键点,然后假装有一个 \(c\) 不是关键点,但是可达,我们取最浅的。相当于,删掉 \(a\to c\) 时,\(c\) 不可达,但是删掉 \(a\to b\) 时,\(c\) 就可达了。说明到 \(c\) 的路径一定要经过 \(b\to c\) 当中的某一个边,也就说明有一个祖先是可达的,与最浅矛盾。

你发现这个证明跟上面的很像,事实上上面的错了就因为经过树边可以经过 \(a\) 的非 \(b\) 子树内的树边,这不会导出存在一个祖先的结论。

每个点成为关键点的时刻可以类似求出。还是让我先写个暴力。

对了。让我们改一下。

你写线段树合并,维护区间赋值以及单点查询,以及合并(加法)即可。不是特别想写。

这个题是不是应该说,你发现当 \(a,c\) 固定,然后你去移动 \(b\) 的时候,找到这个能不能到达的分界点,发现如果突变成能到,那么就存在一个祖先可以管得了它。

或者说,你其实发现这个每个子树内不能到达的区域都是一个连通块,那你为了描述这个信息,你肯定要找出所有的分界点。也就是关键点。然后你去研究关键点。

C

定义 \(f(k,a)\) 表示有多少个序列 \(b\) 经过 \(k\) 轮冒泡排序之后,可以变成序列 \(a\)

给一棵树,节点编号为 \(1\sim n\)\(q\) 次询问 \(u,v,k\) 表示提取出树上 \(u\to v\) 的序列 \(b\),询问 \(f(k,b)\)

\(n,q\le 5\times 10^5\)

你发现一个事,就是我们每次找到 \(a\)\(1\) 在哪里出现的,比方说是 \(p\)。如果不是在开头,那就说明 \(b\) 当中 \(1\) 出现的位置必须是 \(p+k\);否则,说明它出现的位置在 \([1,k]\) 任选。

当然这里要注意如果越界了需要判断无解。

所以对于一个数,我们关心它是不是前缀最小值,以及关心整个序列当中比它小的有几个。

假设它排名为 \(x\),如果它是前缀最小值,那就把答案乘上 \(\min(n-x+1,k)\);如果它不是,那就要求 \(n-x+1\ge k\) 也就是说 \(x\le n-k+1\)

或者,换句话说,我们要求最大的 \(k\) 个数必须在最后,这样就一定有解。然后,我们数一下有 \(p\) 个数是前缀最大值,最后的答案就是 \(k!(k+1)^{p-k}\)

你发现对完了。所以问题变成给你一个路径怎么去求前缀最大值个数。

有个无脑树剖+单侧递归的 3 log 做法,烂完了。

有个离线点分之类的做法,能做到 2 log。

考虑 1 log 做法。

首先向上的部分是简单的,我们考虑怎么做向下的部分。

阅读了 sol。

你改为计算贡献。发现贡献是三维偏序形式。但是如果你事先求出 \(u\to v\) 当中比 \(x\) 大的第一个数,就可以转成二维偏序,就做完了。

posted @ 2024-06-18 20:33  PYD1  阅读(7)  评论(0)    收藏  举报