2023.04 做题记录

本来是准备 whk 两周搞定了再开的,但是。

首先 \(k\) 是可以确定的,如果找不到合适的 \(k\) 答案是 No。

接下来观察一个 k-flower 的组成:有 \(k\) 个四度点,剩下的都是二度点。四度点组成了一个环,每个四度点绕出去一个二度点的环。

这怎么判断呢?首先随便找一个四度点把环拉出来,点都打上标记。接下来每个点再往外面把环一个一个拉出来判。时间复杂度 \(\mathcal O(n)\)

一开始一直在想 \(k\) 是根号级别有没有什么优雅的暴力,因此在这个简单题上废了很多时间。

首先考虑链怎么做。记 \(f_{l,r}\) 为区间 \([l,r]\) 的答案。那么可以删掉最左的,最右的,或者最左最右两个配对,答案加上 \(2\)

那树上是一样的。对于两个点 \((x,y)\),可以 \(x\) 或者 \(y\) 单独在路径上跳一步,也可以两个点同时跳一步。注意特判长度为 \(1,2\) 的情况。时间复杂度 \(\mathcal O(n^2)\)

\(f_i\)\(i\) 结尾的最长子序列,\(g_i\) 为最长方案数。

枚举前面一个 \(j\)\([j,i]\) 区间里选出 \(k\) 个,乘起来。

但是考虑到是 \(i\) 结尾的,所以 \(a_i\) 必须选,所以你可能需要改一下 binom 的系数。

首先我们可以建出一个状态的自动机:有四个状态 \(0,1,2,3\),分别表示比分为 \(0:0,0:1,1:0,1:1\) 的情况。那么加入一个 \(a\) 或者 \(b\) 相当于在他们之间转移。

现在的问题是复制 \(s\) 无限次之后的串,不难发现在自动机上会跳到一个环里。而我们关心的是游戏轮数趋向于无穷大时的胜负情况,因此进入环之前的胜负与答案无关。我们只统计环上的总和,并且算一遍就足够了。

我们定义 \(f_{i,j,a,b,c,d}\)\(s\) 中的前 \(i\) 位,目前 Alice 和 Bob 的分差是 \(j\)\(0,1,2,3\) 四个点分别会走到哪里。转移就枚举加入 \(a\) 或者 \(b\) 即可。

但是这样我们不知道环上的点怎么算贡献。好的方法是枚举 \(2^4\) 个集合,然后钦定环上的点计算次数。

最后沿着状态跳一遍统计答案即可。时间复杂度 \(\mathcal O(2^4\times 4^4\times n^2)\),注意使用滚动数组和 int。

这里还有一个问题:\(j\) 这维数组应该开多大?我一开始写的是 \(2n\),顺利地过了。但是帮 grg 调这题的时候他友好地指出应该是 \(4n\)。我试了一下 \(400\)\(?\) 的情况,确实挂了。很有趣啊!但是 \(4n\) 的话常数很大。所以可能需要好的卡常技巧。

首先离散化。

奇数次,令人联想到 xor。对每个数考虑他的所有出现,每次多出现一个就 xor 1,那么我们要做的就是找到第一个 \(1\)

用可持久化线段树维护值域 \([1,m]\)\(01\) 情况。构建时,加入一个 \(a_i\) 就相当于 \(a_i\) 这位 flip 一下。

但是这样不好维护,所以我们对于每个数随机一个权值,维护前缀 xor。

查询的时候,两棵线段树相减,二分一下。复杂度 \(\mathcal O(n\log n)\)

  • CF917D Stranger Trees *2600 【矩阵树定理,行列式,拉格朗日插值,树形 dp,二项式反演】

首先有一个明显的 \(\mathcal O(n^4)\) 做法:对于原树的边设为 \(x\),非树边设为 \(1\),跑矩阵树得到的 \(i\) 次项系数就是恰好选 \(i\) 条边的方案数。直接多项式乘太慢了,带入 \(n+1\)\(x\),然后拉格朗日插值。

但是给定的是一棵树,而这个性质在如上做法中没有被利用到。我们考虑记 \(g_i\) 为钦定了树上的 \(i\) 条边被选的方案数,设最终的答案为 \(f_i\),从 \(g_i\) 推出 \(f_i\) 显然可以二项式反演。

那么考虑如何算 \(g\)。对于一种方案,分成了 \(k\) 个连通块,每个连通块大小分别为 \(a_i\),那么有 \(\prod a_i\times n^{k-2}\) 种合法的生成树,可以用 prufer 序列的一一对应关系证明。

这样就可以考虑树形 dp了:设 \(dp_{i,j,k}\) 表示 \(i\) 子树中选出 \(j\) 个连通块,当前的连通块大小为 \(k\) 的总贡献。这个 dp 可以通过树上背包做到 \(\mathcal O(n^3)\)

还可以优化状态吗?\(i\) 不能优化了,\(j\) 又是算答案时必须的下标,所以我们只能着手于 \(k\)。但是 \(\prod a_i\) 不好化简,想到利用连乘的组合意义(product trick):现在有 \(j\) 个盒子,每个盒子里面有 \(a_i\) 个球,需要从每个盒子中选出一个的方案数。那么我们就只需要记录当前的连通块有没有被选,就符合这个组合意义了。时间复杂度 \(\mathcal O(n^2)\)

这题其实不算难,但是我可能一直不太会这种风格的数论。

我们假设 \(a\le b\),那么 \(d=b-a\) 是不变量,且 \(g=\gcd(a,b)\) 一定是 \(d\) 的约数。

每次操作,我们假设 \(a=xg,b=yg\),那么目标就是尽量少做 \(-1\) 使得 \(\gcd(x,y)>1\)。又因为 \(g|d\),所以枚举 \(d\) 的约数。而又考虑到修改的次数是 \(x\bmod g\),所以枚举质因数。线性筛预处理一下,每次 \(g\) 至少会翻倍,因此复杂度为 \(\mathcal O(\sqrt A+\log A)\)

做这种奇怪的操作构造题的时候应该先想能不能通过若干次操作组合出一个简单的操作(比如这题的 \(+1,-1\))。

我们先任意调整使得 \(\sum a_i=kn\),如果这一步不能完成那么无解。

接下来,考虑每次选择最大值和最小值。让最大值 \(-1\),让最小值 \(+1\),这样操作若干次之后一定可以使得每个数都变成 \(k\)。注意这里 \(+1,-1\) 都是相对的,也就是说其他 \(n-2\) 个数变化量相同。

一种合理的构造是 \((1,2,3,\dots n-1,n)\)\((n-1,n,\dots 2,1)\),这样 \(a_1\) 加上了 \(n\)\(a_2\) 加上了 \(n+2\),其他数加上了 \(n+1\)

不难发现操作次数是 \(2n^2\) 级别的,可以通过。

LIS 是有经典的 dp 的,我们考虑将其推广到区间问题上。记 \(dp_{i}\) 为当前以 \(i\) 这个数结尾的 LIS,那么转移就是 \(dp_{i}=\max \{dp_j\}+1(j<i)\),依次加入各个数然后转移。

但是现在是区间,不能一个一个算。观察最终选出的 LIS 特点,对于一个区间,如果选了一段,就一定有一种方案选出了一个后缀。

所以我们只需要维护所有 \(dp_{r_i}\) 的值,我们记它为 \(f_i\)。有两种转移,其一是选择整个区间 \(i\),那么 \(f_{i}=\max\{f_j\}+(r_i-l_i+1)\),其中 \(r_j<l_i\);其二是选择一个后缀,也就是 \(f_{i}=\max \{f_{j}+r_i-r_j\}\)

这两个转移都可以用线段树维护区间最大值,具体来说,你需要维护 \(f_i\)\(f_{i}-r_{i}\) 的最大值。

注意需要离散化,最方便的实现是把 \(l_i-1,l_i\)\(r_i\) 都给标记出来。

时间复杂度 \(\mathcal O(n\log n)\)

\(m=1\) 的时候答案是 \(n\)

\(m\ge 3\) 的时候,对于所有和 \(n\) 奇偶性相同并且 \(\le n\) 的数 \(n-2x\) 都可以构造 \([n-2x,x,x,0,0\dots 0]\),并且可以证明所有和 \(n\) 奇偶性不同的都取不到,所以可以 \(\mathcal O(1)\) 算。

\(m=2\) 的时候数位 dp,记 \(f_{n},g_{n}\) 分别为 \(n\) 的方案数和总和,转移会影响到 \(\lfloor\frac{n}{2}\rfloor\)\(\lfloor\frac{n}{2}\rfloor-1\),总的状态数有 \(\mathcal O(\log n)\) 个,就做完了。

喵喵题,太厉害。

考虑对于每个限制 \((a,b)\) 连一条 \(b\)\(a\) 的边,那么最终序列里面 \(x\) 的出现次数最多是 \(1\)\(x\) 的最短路边数 \(+1\),如果有的点走不到答案是 INFINITE,否则是 FINITE。

这样找到了答案的上界,这个上界很好取到,按照 \(d\) 分类然后交替着放就可以了。

UM/bx

题面太抽象了,我们建成一棵树。相当于一个类似于线段树的结构,每次对于一个区间 \([l,r]\),按照题面里的规则分成了两个儿子继续递归,而 \(x_i\) 对应的就是树上代表中间点的节点的深度,问询的就是相邻点的深度差之和。

\(\max (\frac{a_i}{b_i},\frac{b_i}{a_i})\le 2\) 意思是树深度为 \(\mathcal O(\log N)\)

考虑到这棵树的中序遍历是 \(1\sim n\),所以 \(i\to i+1\) 是一条祖先后代关系的路径,深度的差也就是这条路径的长度。

\(\sum \limits_{i=l}^{r-1}|x_{i+1}-x_{i}|\) 不好算,我们给他加上一个 \(|x_r-x_l|\),这样这整个式子就变成了区间 \([l,r]\) 的虚树内边数 \(\times 2\)

考虑 \([l,r]\) 的虚树由哪些东西构成:首先是 \([l,r]\) 原来的点,其次是 \(l\to r\) 路径上不在 \([l,r]\) 内的点,算出点数减一就是边数了。

最后考虑算 \(|x_r-x_l|\),用二分的办法。因为深度不大,复杂度也是 \(\mathcal O(\log N)\) 的。

发现复杂度与 \(M\) 无关。\(M\) 确实可以很大,因为我们只关心深度以内的 \(a,b\) 的值。

首先强连通分量里面有两种颜色就是平局,否则可以缩点,两张图等价。

现在变成了 DAG 的问题。对于 Alice,只有一步操作获胜才能赢。对于 Bob,只有 \(n=2\),两个独立黑点或者一条边,出点是黑的或者全是白点才能赢,否则平局。

时间复杂度 \(\mathcal O(n+m)\)

考虑一个 dp:\(f_{i,j}\) 表示前 \(i\) 行,第 \(j\) 列结尾的弓蛇数量,那么每次转移,如果当作关于 \(j\) 的变化的函数,相当于对于一个区间求和,并且赋值上去,有障碍的地方搞成 \(0\)。可以动态开点线段树。

但是这样有很多的空行,还是太慢了。对于空行,我们观察到做一次操作之后所有的 dp 值都变成一样的了!因此可以先做一次操作,接下来的空行连续段就可以快速幂了。

时间复杂度 \(\mathcal O(q\log m)\)

考虑从低位往高位建立 trie 树。

S 操作相当于对于每个点,交换儿子 \(1,2\);R 操作相当于对于每个点,三个儿子轮换,并且进到儿子 \(0\) 继续递归。

这个操作可以通过懒标记实现。

时间复杂度 \(\mathcal O(3^k+k|S|)\)

一排竖着的积木然后刷颜色或者干什么事情的这种模型会一眼笛卡尔树。

建出小根笛卡尔树。观察到对于某一行如果是 \(01010101\) 这样的,下一行可以相同也可以相反,但是如果出现了连续的 \(00\) 或者 \(11\) 就必须相反,因此考虑记 \(dp_{u,0/1}\) 表示 \(u\) 子树,是否出现 \(00/11\) 的方案数,然后就可以转移了。

时间复杂度 \(\mathcal O(n\log h)\)

所以为什么 \(n\le 100\)

很难想啊这个题,为什么难度只有 2400 出头一点。

找路径显然是不现实的操作,考虑怎么样的 \(a,b\) 选法是合法的。

每条边都是 \(\min\),这个不好搞。但是考虑到整体也是取 \(\min\),所以我们当作两个里面任选一个。

用集合 \(T\) 表示选出的 \(a,b\)。每个点可以分为四类,\(00\)\(01\)\(10\)\(11\),分别表示 \(a,b\) 是/否在 \(T\) 中。

观察到所有的 \(01\) 都能拼起来变成一条链,所有的 \(10\) 也可以拼成一条链。

如果存在 \(00\),那么就有相同个数的 \(11\),我们可以按照 \(01\to 11\to 10\to 00\) 的顺序连成环。

如果不存在,那么 \(01\)\(10\) 必须自成环。

因此合法的充要条件是,全选 \(a\) / 全选 \(b\) / 至少有一个 \(a,b\) 都选。

那么就好做了,考虑贪心。首先选出前 \(n\) 小的 \(a,b\),看看是否符合条件。如果不符合,说明每个点 \(a,b\) 恰好一个在 \(T\) 中。我们用第 \(n+1\) 小的替换第 \(n\) 小的,再看看是否合法。如果还是不合法,那么有两种调整方式:一种是用第 \(n\) 小的替换第 \(n-1\) 小的,另一种是用第 \(n+2\) 小的替换第 \(n+1\) 小的。由于上面那两种方案都不合法,这说明第 \(n,n+1\) 小的两个数来自同一个点,因此替换之后必定是合法的。

时间复杂度 \(\mathcal O(n\log n)\)

一个区间是好的当且仅当长度是偶数并且不存在绝对众数。

平方的做法是,直接 dp。

考虑 cdq 分治。假设现在已经算好了 \([l,mid]\) 的答案。观察到 \([l,r]\) 的绝对众数在 \([l,mid],[mid+1,r]\) 里面都是众数(这是由于摩尔投票的可加性)。

对于 \(mid\),我们找出所有的后缀可能的绝对众数,最多只有 \(\mathcal O(\log n)\) 种,原因是,假设当前的众数是 \(x\),出现了 \(c\) 次,那么至少需要再加上 \(c\) 个另外的数才能翻盘,所以序列长度会翻倍。对于 \(mid+1\) 同理找出所有的前缀。

考虑对于每一种不同的绝对众数做 dp,设绝对众数是 \(x\),把 \(x\) 都当作 \(+1\),不是 \(x\) 的都当作 \(-1\),那么我们要减去区间和 \(>0\) 的区间,这个直接开个桶算个后缀和就行了。

时间复杂度 \(\mathcal O(n\log^2 n)\)

首先有一个结论,\(f(p)=\sum \limits_{i=1}^{n}i(i-p_i)\),硬拆一下题目里的式子就能得到。

先转成期望来做,最后乘回去得到总和。

那么最后的答案和 \(i\) 在操作了 \(m\) 次之后的位置期望是相关的。观察到一个元素操作到一次之后,位置期望一定是 \(\frac{n+1}{2}\),因为 \(j\)\(n-j+1\) 的概率相同,是对称的。所以只需要分类是否被操作到就可以解出位置的期望,进而求得答案。

时间复杂度 \(\mathcal O(n\log n)\)

每次 \(+1\) 可以使得数位和 \(+1\),每次进位会使数位和 \(-9\)

考虑设 \(dp_{i,j}\) 表示第 \(i\) 位恰好有 \(j\) 个数进位的最小数字和。从 \(i\)\(i+1\) 转移时,先将所有的数按照末 \(i\) 位从大到小排序,这样进位的一定是一个前缀,枚举 \(x\) 的第 \(i+1\) 位值 \(j\),然后加一下转移。

时间复杂度 \(\mathcal O(10n\log a)\)

\(n\) 为偶数时无解,因为边数是偶数。

\(g=\gcd(n,k)\),考虑按照 \(\bmod\ g\) 的余数分成 \(g\) 组,排成一个矩阵。比如 \(n=15,k=6\) 就是:

0 6 12 3 9
1 7 13 4 10
2 8 14 5 11

接下来考虑这样三个步骤:

  1. 把前 \(\frac{n}{d}-1\) 列分别连起来

  2. 把第一行连成一排

  3. 把最后一列竖着连起来

不难发现所有的单步操作里面要连的边都是可以配对的,那就做完了。

时间复杂度 \(\mathcal O(n)\)

\(S\)\(X,Y\) 的最长公共子串。

\(|S|>0\) 的时候,可以先将 \(X\) 改成 \(S\),再改成 \(Y\),此时答案为 \(|X|+|Y|-2\times |S|\)

\(|S|=0\) 时,不能删成空串,所以必须保留一个不是 \(Y\) 包含字符的字符,并不断执行“加入相邻的一个字符,删除当前字符”的过程。这个过程相当于一个最短路,将相邻的 \(A_i,A_{i+1}\) 连边,然后找到离某个 \(X_i\) 最近的 \(Y_j\)。设距离为 \(d\),那么答案为 \(|X|+|Y|-2+2\times d\)

最后的问题是怎么求 \(S\),一种不需要高端纸糊船科技的方法是二分答案然后哈希。

时间复杂度 \(\mathcal O(n\log^2n)\),瓶颈在于求最长公共子串,所以不难通过广义 SAM 优化到 \(\mathcal O(n)\)

首先根据 Hall 定理不难发现有解的充要条件是:如果在 \(a_i\)\(+1\)\(b_i\)\(-1\),那么所有前缀和都 \(\ge 0\)

考虑先将所有 \(a_i<b_i\) 的拉出来加入前缀和的贡献,\(a_i\ge b_i\) 的作为替换的备选项,放进一个堆里。

每次找到最前面的前缀和 \(<0\) 的位置,设其为 \(i\),那么我们需要找到一个 \(j\),满足 \(b_j<i<a_j\) 替换使得前缀和变大 \(1\)。注意到这里我们不关心 \(b_j\) 是大还是小,我们只希望 \(a_j\) 能尽可能大,因为这样减操作来的晚一点。因此我们要找到 \(a_j\) 最大的用来替换。

实现的时候其实不需要先判有解或者无解,在执行这个贪心过程中的某个时间点如果出现了找不到替换项的情况是就说明无解。

时间复杂度 \(\mathcal O(n\log n)\)

考虑根据和 \(\frac{K}{2}\) 的大小关系分类。我们叫 \(\ge \frac{K}{2}\) 的数大数,\(<\frac{K}{2}\) 的数小数。

那么两个大数可以连在一起,两个小数不能连在一起。我们要考虑的就是一大一小的情况。

如果一个小数是 \(a\),那么对应的旁边的大数必须 \(\ge k-a\)。我们考虑这样一个过程:从小到大考虑小数 \(a\),把所有 \(\ge k-a\) 的大数都加入,然后考虑 \(a\) 放哪里。具体考虑的方式就是,目前有一堆数,那么要把 \(a\) 插入,插入完之后会少一个空,这个方案数是可以直接乘的。这样的算法一定是正确的,因为 \(a\) 是单调的,所以会不断加入空格。

最后还需要处理一下相同的问题,重排列除一下阶乘就行了。

时间复杂度 \(\mathcal O(n\log n)\)

\(dp_{i,j}\) 为前 \(i\) 个长方形,上一个结尾在 \(j\) 的最小代价,那么转移就是 \(dp_{i,j}=\min\{dp_{i-1,k}\}+|j-l_i| (k\in [j-len_{i-1},j+len_i])\),其中 \(len_i=r_i-l_i\)

把它当作一个函数 \(f_{i}(j)\),观察到它是凸的,维护一下端点然后用堆合并。

细节比较多,应该要分三段讨论,但是最后的代码并不困难。

时间复杂度 \(\mathcal O(n\log n)\)

\(dp_{i}\) 为确定 \(i\sim n\) 的方案数,那么 \(dp_{n}=n\)\(dp_{n-1}=n^2\)

分三类转移:

  1. \(i\) 位是 \(1\),从 \(dp_{i+1}\) 转移过来

  2. \(i\)\(>1\),第 \(i+1\)\(>1\),那么之后的序列就确定了,所以有 \((n-1)^2\)

  3. \(i\)\(>1\),第 \(i+1\) 位是 \(1\),接下来有一段 \(1\),所以会转移到一些 \(dp_{i+x-1}\),这是一个后缀和,直接记录一下。

时间复杂度 \(\mathcal O(n)\)

考虑怎样的一个方案是合法的:把这棵树分成若干条链,每条链上恰好空出来一个点,这样所有的棋子就会在两个位置之间左右横跳。

但是这样方案还是不一定唯一,因为有可能从半路跳出去到另一条链上。限制唯一的方式就是所有链头互不相邻,链尾互不相邻,链中间的点的相邻点除了自己的链头链尾都是链中间的点。

这个条件也不难 dp,考虑设 \(dp_{i,0\sim 7}\),分别代表:

  • 链头:有无前驱,一共两种

  • 链中间:有/无前驱,有/无后继,一共四种

  • 链尾:有无后继,一共两种。

时间复杂度 \(\mathcal O(n)\),乘上一个大常数。

首先有一个 \(\mathcal O(nD)\) 的做法,设 \(dp_{i,j}\) 为后 \(i\) 次操作走到 \(j\) 是否可行。

观察 \(dp\) 数组:我们每次问询只关心它的一个前缀是不是全是 \(0\),既然是这样,我们不如记 \(f_{i}\) 为第 \(i\) 行的第一个非零的位置,就可以做到 \(\mathcal O(n)\) 了。

我们记 \(V\times t=Q\),表示热量。那么目标就是最大化 \(Q\)

\(dp_{i,j}\) 为第 \(i\) 天,水库内保留至多 \(x\) 升水时最大的 \(Q\)

观察 \(dp_{i}(j)\) 这个函数的性质:是一个上凸壳。转移的方式就是,先进行一个平移,然后将原点与各个转折点连接,重新去一个上界。

这个操作是好做的,用单调队列维护凸壳。时间复杂度 \(\mathcal O(n)\),但是浮点数运算慢的很,注意常数。

大家好,我是不会贪心的小可爱,于是我用随机化过了这题。

有一个显然错误的贪心:每次比较两个球的染色方案,取一个较小的保留。

但是我们充分发扬人类智慧,random shuffle 200 次,然后过了。

讲讲正解。

首先两个颜色是对称的,考虑最大值染成红色。

有两种情况:第一种是最小值也是红色,条件是存在一种最大最小不在一个袋子里的方案。这样红色就确定了,对于剩下蓝色的,相当于选出一部分极差最小,这是好做的。

第二种情况是最小值是蓝色的,那么将每个袋子里的较大值涂红,较小值涂蓝,不难发现是正确的。

时间复杂度 \(\mathcal O(n\log n)\)

因为一定有一个棋子在 \(a_i\) 处,所以有一个简单的 dp:\(dp_{i,j}\) 表示前 \(i\) 个要求,目前除了 \(a_i\) 的另一个棋子在 \(j\)

转移有两种,第一种是 \(dp_{i,j}+|a_i-a_{i+1}|\to dp_{i+1,j}\),另一种是 \(dp_{i,j}+|j-a_{i+1}|\to dp_{i+1,a_i}\)

前者只需要整体 \(+|a_i-a_{i+1}|\),后者只需要维护区间的 \(dp_{i,j}-j/+j\) 最大值即可,用线段树维护。

时间复杂度 \(\mathcal O(n\log n)\)

首先 YY 不能出现,这意味着 Y 是一个独立集。

根据 \(B,C\) 可以确定 Y 是叶子的个数为 \(\frac{C}{2}\)。因此非叶子的个数为 \(B-\frac{C}{2}\) 或者 \(B-\frac{C}{2}+1\),取决于根是不是 Y。可以通过 dp 来确定是否可行,设 \(dp_{i,j,0/1}\)\(i\) 子树,里面选了 \(j\) 个叶子,\(i\) 选了/没选的时候,最多选几个非叶子节点。

时间复杂度 \(\mathcal O(n^2)\)

一个实现技巧是不要 dfs,直接从下往上推。

典题怎么今天才做。

\(P\) 为奇质数集。

首先先差分一下,转化成每次对于两个相差是奇质数的位置同时异或 \(1\)

既然差是奇数,那么可以按照奇偶分两边建成二分图。

我们考虑一下如果达到同时操作两个点 \((x,y)(x<y)\) 的效果需要多少步。

  • \(y-x\in P\) 时,一次操作就能搞定。

  • \(y-x\) 是偶数时,

    • 如果 \(y-x=2\),即 \((x,x+2)\),通过 \((x,x+5)\)\((x+5,x+2)\) 就达到了 \((x,x+2)\) 的效果。

    • 如果 \(y-x=4\),即 \((x,x+4)\),通过 \((x,x+7)\)\((x+7,x+4)\) 就达到了 \((x,x+4)\) 的效果。

    • 如果 \(y-x=6\),即 \((x,x+6)\),通过 \((x,x+11)\)\((x+11,x+6)\) 就达到了 \((x,x+6)\) 的效果。

    • 如果 \(y-x\ge 8\),根据哥德巴赫猜想在 \(\le 10^7\) 时的正确性,可以找到 \(p_1,p_2\) 满足 \(p_1+p_2=y-x\),那么操作 \((x,x+p_1)\)\((x+p_1,y)\) 即可。

    • 因此,无论如何都需要 \(2\) 次操作。

  • \(y-x\) 是奇数时,

    • 如果 \(y-x=1\),即 \((x,x+1)\),通过 \((x,x+7)\)\((x+7,x+4)\)\((x+4,x+1)\) 就达到了 \((x,x+1)\) 的效果。

    • 如果 \(y-x=3\),即 \((x,x+3)\),通过 \((x,x+11)\)\((x+11,x+8)\)\((x+8,x+3)\) 就达到了 \((x,x+3)\) 的效果。

    • 如果 \(y-x=5\),即 \((x,x+5)\),通过 \((x,x+11)\)\((x+11,x+8)\)\((x+8,x+5)\) 就达到了 \((x,x+5)\) 的效果。

    • 如果 \(y-x\ge 7\),那么考虑变成 \(3+2k\) 的形式,这样就能 \(3\) 次完成。

    • 因此,无论如何都需要 \(3\) 次操作。

所以首先考虑 \(y-x\in P\) 的情况,这是一个二分图匹配。接下来,剩下的偶数和奇数个数的奇偶性相同的,因为初始时有偶数个数,尽可能内部匹配。最后可能剩下奇偶各一个,配一起花 \(3\) 次操作即可。

如果用 Hungary 算法做匹配,时间复杂度 \(\mathcal O(V+n^3)\)。如果用网络流可以做到 \(\mathcal O(V+n^2)\)(连边的复杂度)。

不过我怀疑连边有可能(?)可以优化,那么就是 \(\mathcal O(V+n\sqrt n)\) 了。

这个 \(a_i/a_i+n\) 让人觉得很像拆点。考虑拉出一棵 dfs 树,上面的边都是一个方向,从儿子往父亲连,剩下的返祖边全部都从祖先往儿子连。

证明一下其正确性:如果一条边 \((u,v)\) 在无向图上是割边,那么放到有向图上一定也是割边。否则对于剩下的非割边,我们考虑到在无向图上一定是有一个儿子的返祖边到达了自己的祖先,那么也就在一个强连通分量里。因此不会有更多的割边出现,也就取到了最小值。

时间复杂度 \(\mathcal O(n+m)\)

把每个要求挂在右端点。

dp。设 \(dp_{i,j,k}\) 为前 \(i\) 个位置,另两种颜色的上一次出现分别在 \(j\)\(k\) 的方案数。转移的时候,检查每一个要求是不是都符合了,最后答案乘个 \(3\)

时间复杂度 \(\mathcal O(n^3)\)

对于每行每列建点,再建立源点和汇点。

对于起点,\(S\) 向行点和列点连边。

对于终点,行点和列点向 \(T\) 连边。

对于中间的空点,行列点之间互相连边。

求最小割就是答案。

时间复杂度 \(\mathcal O(flow(n+m,nm))\)

考虑枚举位数,并且首尾两两配对,这样每一位权值为 \((a-b)(10^x-10^y)\),其中 \(a,b\) 分别为 \(N\) 的第 \(x\) 位和第 \(y\) 位。

如果一位选完之后,后面的全部加起来最大值也不够的话就要提前推掉,而这个最大值是可以预处理出来的。

这样直接搜就对了!

时间复杂度分析:每一位至多有两种选的方式,所以复杂度是 \(\mathcal O(2^LL^2)\),其中 \(L=18\)

就当作学习重构树的第一个应用了。自己想的,虽然比较板子。

首先建立大根 Kruskal 重构树,这样对于一个点 \(u\),通过 \(\le x\) 的边可以走到的点集就是 \(u\) 不停往上跳,最浅的一个祖先,满足点权 \(\le x\) 的点,它的子树。对于这个点,可以直接倍增求出来。

接下来相当于子树 \(k\) 大,在 dfn 序上用可持久化线段树查询 \(k\) 大即可。

时间复杂度 \(\mathcal O(n\log n)\)

\(\mathcal O(n^2)\) 建图太慢了,考虑优化。

对于 \(x,y\) 坐标分别排序,然后相邻点连边。考虑任意三个点,最大最小两个的边显然是没有必要存在的,因此这样连边是正确的。

跑个最小生成树。时间复杂度 \(\mathcal O(n\log n)\)

首先,如果一对点中有一个不在边界上,那么这对点是不需要考虑的。原因是,别的边都可以从旁边的缝隙穿过去,相当于把这两个点的连线挖掉之后新建了一个平面。

那么就考虑边界上两两配对的问题,也就是不能相交。考虑选一个点绕一圈,把第一次出现记为 \((\),第二次出现记为 \()\),每种括号是不同的。那么有解的充要条件就是括号序列合法,排序了之后判一下即可。

时间复杂度 \(\mathcal O(n\log n)\)

有两种分析方法。

方法一:贪心

考虑贪心的策略:按照 \(L\) 从小到大排序,每次尽量先搞定 \(L\) 小的,如果到某个位置塞不下了,那就换成 \(R\)。怎么换 \(R\) 呢?当然是从 \(R\) 里面找一个最小的移到右边去。

最后看一下有几个人没座位,就是答案。

时间复杂度 \(\mathcal O(n\log n)\).

方法二:Hall 定理

考虑到人和椅子是一个二分图匹配的关系,联系到 Hall 定理。完美匹配的充要条件是对于每个点集,相邻点集合大小不小于点集大小。

那既然连的边是 \([1,l_i]\cup[r_i,m]\),对于一堆人,最后的并也一定是 \([1,l]\cup[r,m]\) 的形式。

现在我们要把图补成完美匹配,那答案就是 \(n-\) 最大匹配。

这里可以像上面一样考虑贪心,还有一种运用线段树的方法。

我们现在要做的就是找到一个点集,使得 \(S+|\cup(l_i,r_i)|-m\) 最大。把区间排序了之后扫描线即可。

时间复杂度也是 \(\mathcal O(n\log n)\)

首先确定 \(N\) 的位数:不停地问 \(10^k\),从大到小,直到出现了一个 N 那就确定了位数。

但是这里要特判第一次 \(10^9\) 就出 Y 的情况:这种时候答案是 \(10^k\) 的形式,用 \(9...9\) 去问就可以了。

否则,既然知道位数了,就可以直接二分。

问询次数分别是 \(2\lg n\)\(\lg n+\log n\)

我们充分发扬人类智慧:随个边的顺序,建出生成树,剩下多了一堆边。首先在树上找到 \(1\)\(n\) 的路径,把路径上所有边都删了,分成若干个子树。

根据数学直觉,在随机生成树之后,对于剩下的所有边,如果两端不在一个子树内就不能加进去。

所以我们只取不在同一个子树内的边来计算答案。

这样速度快得飞起,在 \(n=15,m=105\) 时随 \(5\times 10^5\) 次都可以在 2s 内卡过。

以上是我 vp 时候做法的整活,接下来是正经做法。

考虑求出最多保留多少。状压 dp,设 \(dp_{S,i}\) 为考虑 \(S\) 中的点,\(1\to i\) 只有一条路径能加上多少边。预处理一些转移,然后枚举子集,时间复杂度是 \(\mathcal O(n3^n)\)

这个题是有故事的。既然今天做到了,要不就明天讲讲故事?

首先建出重构树,这样就可以知道两两之间的最大宽度。

考虑人吃糖的时候,可行边的变化情况:一定是最小的那条边最先断开,这样两边就走不通了。

假设两端是 \(u,v\),宽度是 \(w\)。那么有一个结论是,先把 \(u\) 或者 \(v\) 吃完了不会更劣。考虑存在另一个走法,是先吃了一部分 \(u\),过去吃好 \(v\) 再回来,这就说明吃完 \(v\) 加上部分 \(u\) 还是不超过 \(w\),因此可以直接把 \(v\) 吃光。这时候我们相当于把整个树的问题化为了子问题。

这相当于一个树形 dp,只不过是按照重构树的点顺序来做。

时间复杂度 \(\mathcal O(m\log m)\)

首先对于每个点找到最近的充电站。

假设在 \(i\) 点时的电池容量为 \(x_i\),最近的充电站距离为 \(dis_i\),容量为 \(C\),那么必须满足 \(dis_i\le x_i\le C-dis_i\),原因是,要到一个充电站得花这么电,从充电站回来也要花掉电。

通过这个式子不难推出 \(C\ge dis_i+dis_j+w_{i,j}\)\(w\) 是两点间的边权。相当于每一条边有一个下界限制,因此建 Kruskal 重构树(最小生成树),输出 LCA 处的点权。

树剖 LCA 其实很好写啊!之前一直只会写大常数倍增......

时间复杂度 \(\mathcal O(m\log m)\)

显然需要建出 Kruskal 重构树。

这样我们要求的就是 \(x\) 和各个白点的 LCA 的权值最大值,这相当于 \(x\) 和所有白点的 LCA 的权值。

求一个点集的 LCA 有一个技巧:找出 dfn 最大的和最小的求。这样我们只需要维护区间推平 \(0,1\),求 dfn 最大最小值的操作即可。这个是可以通过线段树实现的。

时间复杂度 \(\mathcal O((n+q)\log n)\)

SOS dp 板子题,照着 UM 的题单做的。

转化成若干个数的 \(\operatorname{and}\)\(0\) 的方案数。设 \(f_S\)\(S\) 是多少个状态的子集,\(g_S\)\(S\) 是多少个状态交集的子集。那么不难发现 \(g_S=2^{f_S}-1\),而 \(f_S\) 可以通过 SOS dp(高位前缀和)求得。

最后通过一步容斥就能得到答案,\(g_S\) 的容斥系数是 \(popcount(S)\)

时间复杂度 \(\mathcal O(2^mm+nm)\)

有点意思。

首先第一段前缀是要特殊搞定的,可以整一个 \(\texttt{aaaaaa....}\) 这样的东西,最后会多一点,补一堆 \(\texttt{abcabcabc}\)

接下来对于每一段,假设 \(\Delta c=c_i-c_{i-1}\)\(\Delta x=x_i-x_{i-1}\),显然当 \(\Delta c>\Delta x\) 的时候无解,否则和上面一样,找一个新的字符复制一堆,最后补上一些 \(\texttt{abc}\) 隔开。

由于 \(k\le 20\),我们最多用到 \(21<26\) 个字符,符合条件。

首先考虑 \(e_x\)\(x\) 处的期望步数,这样列出一个方程。

根据经典套路,\(e_x=a_xe_{fa_x}+b_x\),然后从 \(t\) 开始带入消就能得到所有系数,进而推出所有的 \(e\)

有一个更有趣的方法。拉出 \(s\to t\) 路径上的点,拆成一堆子树。对于所有 \(v\) 我们都能证明在子树内的时候 \(e_v=\frac{deg_v}{deg_p}e_p\)\(p\)\(v\) 的父亲。

于是可以直接两遍 dfs 求出答案。

时间复杂度 \(\mathcal O(n)\)

这样我们同时也可以证明答案一定是一个整数,根本不需要求逆元。

最近做了一堆重构树,于是自己想出来了这个题。三年前我在这题中获得了 \(7\) 分的高分。

首先考虑一下有解的条件,有度数 \(\ge3\) 的点或者有环,因为有环可以都搞到环上换好了跑回去,如果有三度点可以像平时倒车入库那种让位子方法,一个先出去,另一个进去了再跑。

建个重构树,需要同时维护标记:是不是一条链,因为链是无解的。其他的和正常的瓶颈路差不多。

时间复杂度 \(\mathcal O((n+q)\log n)\)

重要的思想,遇到这种题的时候,不一定要考虑对于每个 \(x\) 都算一遍,可以考虑各个部分对答案的贡献。

观察到只有 \(x\)\([a_i,a_{i+1}]\) 中时,才会产生贡献,而这个贡献是很好表示的,可以通过差分计算。

时间复杂度 \(\mathcal O(n)\)

这题想到做法之后实现和细节都很简单,但是最难的就在于第一步思想。

暴力模拟,每次对于所有 \(\ge n\) 的都除一下。

时间复杂度:每一轮操作我们可以认为是 \(\mathcal O(n^2)\) 的,经过每一轮之后,最大值会减少到原来的 \(\frac{n-1}{n}\),因此复杂度大致是 \(\mathcal O(n^2\log_{1.02}V)\),在 \(5\times 10^6\) 以内,可以轻松通过。

当然应该也可以二分(?)没写,不想写了。

题目可以理解为在外向基环树上给每个点一个非负权值,使得每个点的权值都等于出边指向点集权值的 \(\operatorname{mex}\)

首先确定子树的点,可以从叶子是 \(0\) 开始反推,这样就只剩下环上的点了。

现在只需要满足相邻点是不同的,每次可以做 \(+1\) 操作,不难发现只有奇环并且所有点的值都相同时无解。

时间复杂度 \(\mathcal O(n)\)

超级好理解的做法!

考虑要使得字典序尽可能小,倒着考虑。我们现在相当于从 \([1,n]\) 中选出一组 \(x,y\),满足 \(x,y\) 可以在一组里,放到最前面。接下来就分成了 \([1,x-1],[x+1,y-1],[y+1,n]\) 三个子区间,可以继续处理。

\(x,y\) 的合法性也很显然:对于区间 \([l,r]\),应该满足 \(x\equiv l\pmod 2,y\equiv r\pmod2\)

因此用 st 表维护奇偶位上的区间最小值。用一个堆记录当前的可行区间,每次选出最小的那个拿出来分成三半再放回去。

时间复杂度 \(\mathcal O(n\log n)\)

考虑怎么样的一个点集可以作为一组:从小到大加边的时候一定有一个时刻是一个团。

考虑建出 Kruskal 重构树,这样一个合法组对应一个子树,也就是一个区间。现在问题转化成了,一些区间,选出 \(k\) 个并是 \([1,n]\) 不难通过 dp 做到 \(\mathcal O(n^2)\)

建树的时候,由于边权是一个排列,可以把对应边记下来,省去排序的 \(\log\)

posted @ 2023-05-05 09:21  PetitSouris  阅读(94)  评论(0)    收藏  举报