典题回顾

hint 先考虑不去掉 $k$,由求和子集的对称性很容易猜想答案就是 $0$。如何证明?

利用对称性。\(S=\{1,2,\dots,p-1\}\),试着找到一个双射 \(f:S\to S\),可以知道在 \(f\) 的映射下答案是不变的。

我们可以找原根。设 \(g\)\(p\) 的一个原根,\(\{1,2,\dots,p-1\} = \{g,2g,\dots,(p-1)g\}\)

然后再考虑答案。若前面的集合答案是 \(x\),后面的就是 \(xg^t\)。相等可知 \(x=0\)。关于 \(t\) 的大小可能需要讨论讨论。

最后建立递推式即可求得最终答案。

hint 整体考虑一次操作对数列的改变。这会使数列多一个数并且数列的和会增加 $k$。

如果 \(k\)\(0\),操作带来的改变就简单许多,仅仅多一个数而总和是不变的。此时的答案很容易讨论得出。提示:考虑终局下每一个相同的数是被谁生成出来的。

\(k\) 不为 \(0\),数列的总和就取决于操作的次数,讨论起来较复杂。如何让这个和不随操作数变化?

考虑式子 \(x+k=y+z\),有一定对称性。两边同时减掉 \(2k\)\(x-k=(y-k)+(z-k)\),这提示我们 \(k\) 在每一次操作的影响可以在所有操作开始之前算清。也就是说,如果在最开始我们把所有数都减掉 \(k\),那么之后的操作,\(k\) 不再影响总和。

hint 如果求的是路径数?矩阵快速幂板题!

现在变成长度最值,只要将矩阵乘法的两个运算 + * 替换为 min(max) + 即可,易证满足结合律。

hints
hint1 先考虑求某个 $\mathrm{W}(S_i)$。一个显然的贪心是如果当前最小值大过 $k$,直接用操作二,小于 $k$ 用操作一,一定不劣。

接下来我们要考虑的可能是讨论往现在的集合加(或者删)一个数会对答案产生怎样的变化。

为了研究这个变化,我们需要获得比原来的贪心更多的信息,考虑把原来的贪心写成 dp。

hint2 倒着 d,$f_i$ 表示总共已经减掉 $i$ 了的情况下,还需要至少多少次才能清空集合。

每次从 \(i+k\) 以及 比 \(i\) 大的下一个在集合中的数 这两个点转移。考虑到 \(f\) 的单调性,其实就是找下标更大的 \(f\) 转移过来。

怎么处理新加点带来的改变?

hint3 如果强行讨论,确实可以发现一些能算作规律的东西......这个过程中你会发现改变了的 $f$ 是很多段,不好直接处理。

“比 \(i\) 大的下一个在集合中的数”这个转移有点不常规,试着修改一下。想想我们先前的贪心。

hint4 什么时候用操作一?只有在某个集合中的点左边长度为 $k$ 的范围内的那些 $f$,才会用这个转移,其余情况下都是用的操作二。也就是说,选择第二个转移的 $f$ 也是一段一段的,而且一个很好的性质是这里的每一段都是从一个 $f$ 转移来的。

再考虑不断加点的过程中,某一个特定的 \(f_i\) 转移取舍的变化。在前一段时间里,这个 \(f_i\) 使用的是转移二,是从一个右边的很远的点转移过来的。新加点的时候,可能转移二的转移点更靠近了,但离这个 \(f_i\) 的距离还是大于 \(k\)。在这段时间内,虽然 \(f_i\) 的转移点变化了,但选择的是转移二没有变,也就是说,它还是和 \(f_{i+1}\) 的转移点一致。这提示我们,这段时间内我们只需要让 \(f_i\)\(f_{i+1}\) 转移过来即可。而当新加点在 \(i+k\) 以内后,\(f_i\) 将永远从 \(i+k\) 转移过来。

我们得到一个惊人的结论,在某一个时刻,所有的 \(f\) 只会选择唯一一个点进行转移。我们成功地把转移的结构变成了一棵树。LCT 即可。

也可使用根号重构的 trick 避免 LCT。

hint
单个询问?二分答案,找出当前答案下(x,y)所在的连通块,判断该连通块是否把岛屿完全包围。由包围的定义可知当且仅当从岛屿出发无法不经过连通块到达边界时,存在通过(x,y)的一条环岛路径。

求所有n*m个格子的答案?延续之前的思路,改二分为降序枚举,问题变成了如何判断增加一格之后就可以形成通过这一格的一条环岛路。由于我们要同时维护可能存在的多条环状连通块,从定义判断变得不太现实,我们要做到只看连通块本身就能判断是否包围住了岛屿。

考虑是什么让原本无法包裹住岛屿的连通块,增加一格(x,y)之后就变得能包裹住了。显然通过(x,y)相连的那两端一定已经事先连通了,但仅仅如此不够,这两端一定还要是**绕过**岛的另一边之后重新在这里相遇的。也就是说,仅通过原图的连通性是没法保证连通块一定绕岛的,需要增加信息。

假想一个旅人从(x,y)向某一端出发,绕岛的一周再回到(x,y),这个人如何才能知道,自己是真的绕了一周,而不是绕了一半途中迷路原路返回了呢?那么我们就在绕岛必经之路上设置一个监察点,旅人通过了这个点后,就知道只要自己能不再越过这个监察点而回到(x,y),那么自己就真的绕了一周。因为一旦返回,必然会再次越过这个监察点。于是旅人尽管走,只要回到(x,y)时经过了奇数次监察点,就一定是从另一端绕回来的。增加的信息就是越过监察点的次数。

监察点可以设置为从岛屿某处出发的一条射线,将原图中一个点拆成没越过和越过两个点,就可以用(x,y,0)与(x,y,1)的连通性判断。于是问题转化为kruskal重构树上离线lca,也可以在维护并查集的同时维护set来判断是否有询问需要解答。

给定一张图,图中每条边都有一个区间 \([l,r]\) 表示存在时间,对每一个点,求所有使得该点与 1 号点连通的时间点之和。

hint

考虑使用并查集维护连通性。问题在于如何删边。

利用线段树分治+可回退并查集,可以保证加边删边操作时时刻刻构成一个栈,便于并查集的维护。

如何对整个与 1 相连的连通块同时加上一个值?由于并查集是有根树,我们自然想到利用 lazy 的思想,定义每个点的真实值等于这个点到根的路径上所有点的 lazy 和,于是就把子树加操作转化成单点加操作。注意这里 lazy 是不下放的,原因是下放保证不了复杂度(一个点不止有两个儿子)。

不过这里的加边和删边要额外处理。v 连向 u 的时候,为了保证上述性质,v 的值需要减去根到 u 路径上的值之和,断开 v 到 u 的边的时候要加回去。值得注意的是,并查集的连边操作均是在两个根之间的,所以这里就简化为 v 跟 u 两个点的操作了。

给定两个序列 \(f_i\)\(g_i\),对任意 \(1\le i<j\le n\),有 \(i\) 连向 \(j\) 的边当且仅当 \(f_i<f_j\)\(g_i<g_j\)。求该图中三元环的个数。

hint 三元环是高度对称的,很难直接对其计数,那么考虑其反面。其反面可以看作是三个点之中有一点向另外两个点都连了一条边,于是可以用这个出度为 2 的点对这种环计数。

给定长为 \(n\) 的序列 \(a\) (250),求 \(a\) 中每种非空子序列出现次数的立方和。

hint 考虑立方的组合意义。

我们将某一种非空子序列的所有出现拿出来,假设有 \(k\) 个。如何获得 \(k^3\) 呢?从所有出现中可重复的选三个,其方案数就是 \(k^3\)

于是立方和就可以转化为在 \(a\) 中任选三个子序列,且这三个子序列相同的方案数。

dp 需要前缀和优化,除了用容斥直接计算前缀和数组,也可以多开几个数组,边 dp 边高维前缀和。

同上,但是零次方和(即本质不同子序列的个数)。

hint 只要想清楚重数是如何出现的就能轻松列出 dp 式子。

现在加入第 \(i\) 个数,那么会多出来(包含重数)\(f_{i-1}\) 个以 \(i\) 结尾的子序列。考察这 \(f_{i-1}\) 个序列中有哪些是之前出现过的。因为必须以 \(a_i\) 结尾,如果此时 \(a_i\) 是第一次出现,必然不会重复;如果以前出现过,设上一次出现 \(a_i\) 的位置是 \(t\),那么所有以 \(t\) 结尾的子序列一定在这 \(f_{i-1}\) 个序列里面,并且在此之前以 \(a_i\) 结尾的子序列全部都被以 \(t\) 结尾的子序列囊括了,因此重数刚好就是 \(f_{t-1}\)

初始没有边的 \(n\) 个顶点的图被复制了 \(d\) 次,给出 \(m\) 次操作,每次连接某张图上的两点,并询问操作后有多少点对在每张图上都联通。

hint 考虑某两点在每张图上都联通的等价转换。因为每个点在每一张图上都会唯一属于一个连通集,两点在一张图上联通就相当于这两点在这张图上所在的连通集相同。又考察某一点在全体图上所属的每一个连通集,这些连通集又构成一个集合,代表这一点在全体图意义下的连通性。如果两点在每张图上的连通集的集合相同,就等价于在每张图上两点都在同一个集合,这正是我们需要计数的点对。

于是我们需要快速判断集合相等。设法维护每个点对应的集合的哈希值,就可以在合并的时候快速判等。为了计算点对的数量,使用启发式合并,枚举小集合的所有点,这些点由于从属连通集改变而有哈希值改变,此次改变可能使得与其他的点(值得注意的是这些点一定落在大集合内)的哈希值相同,这就说明这两个点连通了,应该计入答案。

在树上动态加点,点有点权,每次操作给出 \(u\)\(s\),表示从根走到 \(u\),每走到一个点就拿走那个点的点权(不恢复),直到总共拿走恰好 \(s\) 或拿完 \(u\) 的点权为止。给出每次操作拿了多少点权。

hint 只讨论在线做法。显然每个点被拿完后就不需要再走到,于是每次操作可以从第一个不为零的点开始走。

为了找到第一个不为0的点,可以对根到自身都为0的点打上标记,这个标记有单调性,很容易想到倍增,而且倍增可以适用于动态加点的情况,清空后标记也很好维护。

如何决定这个点拿完之后下一步往哪个儿子走?其实很简单,不需要找这个儿子,每次都倍增即可。

每次询问以 \(r\) 为根的子树中编号的 lcm 不大于 \(x\) 的点对数

hint 先考虑合并子树的做法,由于 lcm 的特性,单点对一个集合的 lcm 不好找小于 x 的部分。我们注意到两个数的 lcm 较无规律,所以考虑直接枚举所有可能会被询问计数的点对和它们的 lcm。

在此之前先看看不大于 \(n\) 的点对数量,答案是 1 到 n 每个数的因数个数之和,或者利用枚举倍数的方法,可以估计得到 \(O(n\log n)\) 。进一步估计 lcm,肯定不会大多少。设 \(\mathrm{lcm}(x,y) = t\),则可以写成 \(t=abc\) ,其中 \(c=\gcd(x,y)\)\(a=\frac{x}{c}\)\(b=\frac{y}{c}\)。于是要枚举 \((x,y,t)\),在不强制 \((a,b)\) 互质的情况下等同于枚举乘积不大于 \(n\) 的三元组 \((a,b,c)\)。实际枚举时可以先枚举 \(a\),再枚举 \(a\) 的倍数 \(ab\),最后枚举 \(ab\) 的倍数 \(abc\)

\[\sum_{a=1}^n\sum_{b=1}^{n/a}\sum_{c=1}^{n/ab}1\approx \sum_{a=1}^n \frac{n}{a} \sum_{b=1}^{n/a}\frac{1}{b}<\sum_{a=1}^n \frac{n}{a} \sum_{b=1}^{n}\frac{1}{b}=O(\log n)\sum_{a=1}^n \frac{n}{a}=O(n\log^2n) \]

满足 \(\mathrm{lcm}(x,y)\le n\)\((x,y)\) 对数小于乘积不大于 \(n\) 的三元组的组数,也有 \(O(n\log^2n)\) 的上界。

枚举出所有可能对答案有贡献的点对后,可以从小到大枚举 lcm,每次加入以当前枚举到的值为 lcm 的点对,再处理这个 lcm 的询问即可。加入点对就是在根到 lca 的路径上都 +1,表示这段路径上的还未解决的所有询问都算上了这个点对。

给定n对限制xi yi,一个01串被称为好的当且仅当它能被恰好分成n个子串(可以为空),且第i个子串中的0的个数不超过xi,1的个数不超过yi,问有多少个好的01串

hint 先考虑1对限制的情况,利用组合数的性质,答案是 $\sum\limits_{i=0}^{x}\sum\limits_{j=0}^{y}\binom{i+j}{i}=\binom{x+y+2}{x+1}-1$。

当限制变成n对时,直接将每一对限制的答案乘起来会算重,原因是一个合法串可能有多种合法的划分方式。每个合法串,有几种划分方式,就被算了几次。

所以为了不算重,我们要对每一个合法串钦定一个唯一且只有该串拥有的划分方式,也就是要做到合法串到划分方式的一一对应关系。

考虑合法串的判定,一个显然的贪心是按顺序挨个考虑,如果当前子串不能再放入下一位时,就开辟一个新串。尽可能晚地划分一定是不劣的。容易发现,这样的划分方式同样是唯一的,于是可以利用这种划分进行dp。

dp状态中除了当前子串的编号,还有一位用来表示“是因为0还是1达到了最大值才划分出这一段的”。如果是0,那么下一段用这个状态转移的时候,第一位必须放0,否则就与状态定义矛盾了。

统计答案时,由于最后一段可能不满,需要额外计算最后一段的方案数。

取值为 \([0,2^k-1]\) 的数组 \(\{a_n\}\),价值定义为 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n(a_i\oplus a_j)\operatorname {dep}(\operatorname{LCA}(i,j))\),求使得价值最大的 \(a\) 的个数。

hint 首先,每一位之间等价且不互相影响,故只需要考虑 $k=0$ 的情况。

观察式子,每个点对的贡献在 lca 处会被算 dep(lca) 次,相当于这个点对会在根到 lca 的路径的每个点上各算一次,进而转化为最大化所有子树内部的点对贡献的和。

现在有一个显然的贪心:只要保证每个子树都能取到最大值,那么总价值也一定是最大的。构造也很简单,只要每个子树内部 0 和 1 的个数最相近即可。

所以只需要对这种情况计数。考虑 \(f[i][0/1]\) 表示以 \(i\) 为根(子树大小为奇数)的子树中 0 多一个或 1 多一个的方案,直接合并是一个卷积,怎么办?

注意到 0 多一个和 1 多一个的方案是一一对应的,故 \(f[i][0]=f[i][1]\),这样就不需要卷积了,只需要用组合数合并一下即可。

给定 \(\{a_n\}\{b_n\}\),在第 \(i\) 天选择编号 \(j\),可以获得 \(a_j+ib_j\) 的价值。在不允许连续两天选择同一编号的情况下,求 \(m\) 天内能获得的最大价值。

hint 考虑朴素的 dp,$f[i][j]$ 表示在前 $i$ 天中第 $i$ 天选择了编号 $j$ 的最高价值。观察 dp 的转移,可以发现:第 $i$ 天的所有 $f$ 只需要第 $i-1$ 天的最大的 $f$ 和次大的 $f$ 就能够算出。所以考虑只维护每一天的前两大的 $f$。

进一步观察可知,只需要维护每一天的前三大的编号即可正确维护 \(f\)。这是因为如果用第四大进行转移,那么前三大的编号至少有两个也是合法而可以用于转移的,这样一来第四大的编号算出来的 \(f\) 至少是第三大。

于是我们把先前 dp 的状态和转移都压缩成了 \(O(1)\),之后考虑如何维护编号前三大。

通过维护凸包可以求出每个位置的最大编号。考虑一个位置 \(i\) 的次大编号的可能构成。凸包在 \(i\) 处的直线是最大,不具有成为第二大的可能,但是该直线相邻的两条直线可能成为 \(i\) 处的次大,且整个凸包只有这两条直线有可能。

在这个凸包之外的在 \(i\) 处最大的直线,是第三个也是最后一个可能成为 \(i\) 处的次大的直线。所以可以考虑对剩下的直线再做一次凸包,此凸包在 \(i\) 处的直线和上一个凸包在 \(i\) 的附近的两条直线就是所有可能成为 \(i\) 处的次大编号的直线。

第三大编号则同理,再维护第三个凸包即可。

两边各有 n(1e5) 个点的平衡二分图,求添加一条边能使得二分图最大匹配增加的方案数。

hint 考虑用网络流跑出来一个最大匹配。添加一条边 (u,v) 后最大匹配能够增加,这说明多了一条经过该边的增广路。这等价于在残量网络上 S 能到达 u,v 能到达 T。所以只需要计算 S 能到达的左部点的数量,能到达 T 的右部点的数量,相乘即可。

也可以这么想,一条从 S 到 u 再经过若干条边最后到 v 再回到 S 的一条路,可以在匹配数不变的情况下把 u 从为匹配点变成匹配点,把 v 从匹配点变成未匹配点。

此题用 isap 反而不如 dinic,猜测是 dinic 在二分图和单位容量的图上有特殊性质跑的比较快。

大小为n的排列ai,每个数有价值bi,对1~n的每一个k,求LIS小于等于k要删掉的数最小价值是多少。

hint 定义二元关系 $\{(x,y):x简要证明 Mirsky 定理。设最长链长度为 \(d\),则这 \(d\) 个点任两个不可能再同一个反链里,故反链覆盖至少为 \(d\)。考虑构造这样一个方案,它用恰好 \(d\) 条反链覆盖所有点。定义 \(f(s)\) 是以 \(s\) 为最小元的最长链长度,那么 \(f\) 相同的所有点一定构成一条反链,这样的反链恰好有 \(d\) 条。

用 dp 求解 LIS 时,每个位置的 dp 值就是上述的 \(f\)

(转化后的题意)初始有n(2000)个点,l(4000)次加边操作,q(1e6)个询问。每次加一条有向边,然后若干次询问从a是否能走到b。

hint 如果考虑每加一条边会给连通性带来怎样的变化,会发现每次加边都需要考虑 $n^2$ 个点对的关系,这显然是承受不了的。

那么不妨在最开始就考虑每个点对相对于边的关系。考虑找到任意两点之间的路径,走的最晚被加的边最早是哪条。

对每个点做一次 dijkstra,由于是取最大值而非加和,值域很小,可以通过把堆改为 \(l\) 个桶的方式做到线性(暂时不知道怎么做到)。或者可以从小到大加入边,如果现在加入的这一条边的起点能够到达,就从边的终点出发 bfs,也是线性的。

posted @ 2024-01-10 23:18  nkxjlym  阅读(35)  评论(0)    收藏  举报