瞎做题一句话题解&待做题

待坑题:

UR1T3:仙人掌上点分治+奇怪的优化
ULR1:阴间题组T3~T6
dij网络流模板
【ZJOI2017】多项式:奇怪的倍增
【CTSC2017】最长上升子序列:杨表练习题
CF1477F 奇怪的实数域内期望


目录


UR1T1

https://uoj.ac/problem/21

发现答案是\(\sum a_i-(x-1)\sum\lfloor\frac{a_i}{x}\rfloor\)

枚举\(x\),尝试快速计算\(\sum\lfloor\frac{a_i}{x}\rfloor\)。计算的时候按照长度为\(x\)分段。

时间\(O(m\ln m)\),其中\(m=\max a_i\)


UR1T2

https://uoj.ac/problem/22

发现对\(x\)有影响的是从左往右的一个单调递减子序列(称关键序列)。贪心找关键序列序列(选择最近的一个更小的)。

先对\(a_i\)从大到小排序,然后DP搞,转移看看每个\(a_i\)是否在关键序列上。

剩下的问题相当于:假设选入关键序列的数是\(a_{b_i}\),要将\((b_{i-1},b_{i})\)中的数插到\(b_i\)后面的任意位置。

从后往前,相当于\(b_i-b_{i-1}-1\)个数插入\(n-b_i\)个数中。写出\(O(n^3)\)DP,简单优化到\(O(n^2)\)


UR2T1

https://uoj.ac/problem/31

前缀和之后零点之间看看是否反转即可。


UR2T3

https://uoj.ac/problem/33

显然可以把\(gcd\)变成因数,最后反演回来。

先处理祖先后代关系的情况。对于非祖先后代关系的情况:

点分治,计算跨过重心的贡献。分别计算中心(记为\(c\))所在的子树的贡献,和\(LCA\)在中心到根的路径上的贡献。

对于前者,记下子树中各深度点的个数(记为\(cnt_i\))。根据\((\sum a_i)^2=2\sum_{i<j} a_{i,j}+\sum a_i^2\),分别计算\(cnt_c\)\(cnt_z,z\in son(c)\),即可方便计算。这部分时间复杂度显然。

对于后者,枚举\(LCA\)(设为\(x\)),记下\(x\)的子树中除了\(c\)所在的子树中各深度点的个数。计算时枚举贡献\(d\),算出\(d\)的倍数的深度的点的个数,然后计算\(c\)子树中的个数,发现这相当于\(query(d,r)\),询问\(c\)\(dep_i\mod d=r\)的个数。把这个记忆化即可过。时间复杂度分:前面一步不是问题,问题是计算\(query(d,r)\)。当前分治连通块大小为\(S\)。当\(d< \sqrt S\),把所有可能的\((d,r)\)计算出来的总时间是\(O(S\sqrt S)\);当\(d>\sqrt S\),计算一次的时间复杂度为\(O(\frac{S}{d})=O(\sqrt S)\),由于计算\(query(d,r)\)的总次数为\(O(S)\),所以总时间也是\(O(S\sqrt S)\)。算上点分治,总时间复杂度还是\(O(S\sqrt S)\)


ULR1T1

https://uoj.ac/contest/57/problem/574

有个结论:\(n\)\([0,1)\)中随机的数的第\(k\)大期望为\(\frac{k}{n+1}\)。很好感性理解但是没有在网上找到证明,自己尝试强行积分结果搞出了个不知道怎么化简的式子

于是一个选了\(k\)个的状态的贡献为\(\frac{1}{(n+1)\binom{nm}{k}}F_k\)。问题变为统计选了\(k\)个的系数。

对于一对\((x,y)\),可以二维容斥。此时\(k\)的系数为\(\binom{n}{i}\binom{m}{j}\binom{i}{x}\binom{j}{y}(-1)^{i-x}(-1)^{j-y}\binom{(n-i)(m-j)}{k-im-jn+ij}\)

可以分两步进行:设\(f_{0..nm},g_{0..nm}\)。第一步\(\binom{n}{i}\binom{m}{j}\binom{i}{x}\binom{j}{y}(-1)^{i-x}(-1)^{j-y}\to f_{im+jn-ij}\),第二步枚举\(p,q\)\(f_p\binom{nm-p}{q}\to g_{p+q}\)

第二步显然可以卷积。第一步也可以卷积,记\(h(i,j)=\sum \binom{i}{x}\binom{j}{y}(-1)^{i-x}(-1)^{j-y}\),二维卷一下,或者先卷一维再卷另一维,然后\(h(i,j)\to f_{im+jn-ij}\)

EI说第二步可以直接线性做但是我不会。


6945. 【2020.01.07冬令营模拟】星空

https://gmoj.net/senior/#main/show/6945

显然\(k+1\)中的点包含\(k\)中的点(指点集及其系数,而不是关系)。因为那是个二分图。众所周知二分图是个拟阵,所以每次找到合法的扩展中最优的,扩展即可。

一个合法的点集可以对应一个括号序。

假设现在加入\(i\)\(j\),加入左括号\(i\)和右括号\(j\)。当\(i<j\)时很好算,当\(i>j\)时,要求\([i,j)\)的前缀和大于\(0\)

可以线段树维护:记一下当前区间中的最小前缀和。从左到右(从右到左同理)以遇见的第一个最小前缀和为分界点,左边和右边分别维护最优贡献;并且维护以下区间的答案,一个是\([i,j)\)的前缀和都大于最小前缀和,另一个\([i,j)\)存在前缀和等于最小前缀和。搞各种信息后维护即可。时间\(O(n\lg n)\)


LOJ2341. 「WC2018」即时战略(口胡)

https://loj.ac/p/2341

吐槽一下明明是期望、均摊一类的复杂度却把操作次数卡得那么死。不过想想如果是比赛时遇到的话拿大量部分分还是不错的。

二叉树的直接枚举节点,暴力拉出从根到这个点的一条链。

链每次随机一个未确定的点,猜一下在当前确定的连通块的哪边。如果没有猜中就亏了一次。理论上最多\(2n\),不过期望下是\(n+\lg n\)。后面这个\(\lg n\)可以类比最长上升子序列。然而lg 300000=18而只给多3次容错不知道在干嘛。

普通树的,搞个点分树,用\(O(\lg n)\)次搞出它连在哪个节点上,然后拉出一条链。理论上是\(O(n\lg n)\)。我估算了一下,最坏情况下卡得很死,可能还过不去。

可以用类似替罪羊树的方法动态维护点分树。好像也可以\(LCT\)维护重链,然后在重链上跳找重心,\(O(n\lg n)\)(我不会)。再加点随机化可能可以过。怎么都不是严格的时间复杂度啊。

upd:好像不需要\(LCT\)维护重链。(不需要想着找重心)从上往下做,每次在实链上二分,找到转折点。做完之后进行access。这样均摊是\(O(n\lg n)\)


ARC111A~F

A:可以直接模\(m^2\),然而我比较愚蠢维护了个\(am+b\)的形式。

B:连边建图,如果一个连通块中有环,贡献是连通块大小;否则是连通块大小减一。

C:先判掉哪些已经固定的人。如果没有限制下界是\(n-轮换个数\),现在对于每个轮换分别做,找拿着最轻物品的人,然后将自己的物品换回来。由于是最轻所以可以保证这个轮换的人都可以拿住。压到下界。

D:题目保证有解。显然如果\(u\to v\)\(c_u\ge c_v\),所以如果\(c_u\neq c_v\)则其之间的连边方向可确定。如果\(c_u=c_v\)则强联通,否则不能满足其相等。于是对于\(c_u=c_v\)的随便连最终要求它们强联通即可。可以直接建\(dfs\)树,树边向下,返祖边向上,这样一定可行。

E:直接套类欧中\(f\)的板子。

F(口胡):可以发现每个位置可以分开算,唯一的区别是它被操作到的概率。然后考虑对于一个值进行若干次修改后的概率分布,发现是平均的。抓住这个主要矛盾之后应该就能随便做了(推点式子,搞些矩阵乘法之类的)。


LOJ2542. 「PKUWC2018」随机游走

https://loj.ac/p/2542

我才发现原来我不会minmax容斥啊……

题目是对于某种方案计算到达\(S\)中的点的最大时间,由minmax容斥可以转化为到达\(T\)中的点的最小时间。

然后直接树形DP。记\(f_x\)表示\(x\)出发到达第一个\(T\)中的点的期望,可以把其表示为\(f_x=a_xf_{fa_x}+b_x\)的形式。

时间\(O(2^nn\lg mo)\)

另外似乎真的有不用容斥的方法:https://www.cnblogs.com/Mychael/p/9229291.html

大概复述一下:设从\(f_{x,S}\)表示从\(x\)出发目标是经过\(S\)中的点的方案数。转移的时候分\(x\in S\)\(x\notin S\)考虑,后者DP,前者集合变成\(S\setminus \{x\}\)

其实我思考的时候也想过类似的东西但是不对。我认为这个做法的特点是状态设了“目标是……”,这样设就显得对了。


LOJ2841. 「JOISC 2018 Day 4」图书馆

常规题。由\(连通块=点-边\)得每次可以查出集合内的边数。

增量构造,每次二分找出和新加入点相连的边即可。


LOJ2132. 「NOI2015」荷马史诗

k叉哈夫曼树……

容易发现,建出树之后除了倒数第二小的深度的点以外,其它的点都是满的。否则可以调整。

又由于\((k-1)|(n-1)\)时非叶子节点的儿子都是满的,可以感受到直接贪心是对的。

假如不整除,相当于补若干个\(0\)


LOJ2339. 「WC2018」通道(口胡)

差点以为自己出过的题被爆标了。

第一棵树边分,现在问题是选择\(x\in S,y\in T\),最大化\(f_x+f_y+len+dis_2(x,y)+dis_3(x,y)\)

对第二棵树建虚树,假如\(LCA\)\(p\),则问题变为最大化\(f_x+f_y+dep2_x+dep2_y-2dep2_p+dis_3(x,y)\)

可以把\((f_x+dep2_x)\)看成第三棵树的点权。路径权值变为边权和加断点点权和,于是可以看成维护异色点之间的最长路径。

结论:异色点最长路径的两个端点,一定是同色点最长路径的端点进行两两配对得到的。

在虚树上可以类似树形DP,维护子树内同色最长路径是什么。

实现可以做到\(O(n\lg n)\)


LOJ2081. 「JSOI2016」反质数序列(口胡)

显然可以想到最大独立集。把\(1\)讨论去掉,连边(此时和为奇素数)发现连出来的是个二分图。

于是变成了个二分图的最大独立集,跑Dinic应该可以过。


LOJ2523. 「HAOI2018」奇怪的背包(口胡)

很快想出做法查查题解发现大多做法和我不同,慌得一批。只到在洛谷上发现了一个。

显然\(v_i\)\(w_i\)都先分别和\(P\)\(gcd\)之后做。现在问题是,求\(f_d\)表示\(\gcd_{v\in S}v=d\)的集合\(S\)的个数。最后答案是\(\sum_{d|w}f(d)\)

高位min卷积即可。

注意和\(P\)\(gcd\)之后有用的位置只有\(\sigma(P)\)个,因此时间复杂度大概是\(O(\sqrt P \lg P)\)吧。


LOJ3096. 「SNOI2019」数论

如果认为这是数论题你就输了。

钦定\(P<Q\)。枚举\(A\)中某个数\(x\),求\((x+iP)\mod Q\in B\)的个数。在一个\(Q\)个点的图中,连边\((x,x+iP)\),一些点上有权值,问从某个点出发走多少步路径上的权值和是多少。

直接倍增会被卡空间。处理一下每个轮换就好了。


LOJ2002. 「SDOI2017」序列计数(口胡)

分析一下变成计算\(F(x)^n\)\(p\)的倍数次项的和这样的问题。按照套路直接循环卷积+快速幂。卷积暴力卷。


LOJ2477. 「九省联考 2018」劈配(口胡)

二分图匹配。每次尽量匹配最有利的。匹配完之后把同层的边都加进来。第一问就出来了。

第二问,记录下每个历史状态,枚举答案在历史状态中找增广路。这个答案可以二分。


6950. 【2020.01.16冬令营模拟】枇杷树

问题转化为维护\(f(i,j)\)表示\(T_i\)中所有点到\(j\)距离和。可以递归去做,要用到辅助函数\(dis(i,j,k)\)

记忆化一下,复杂度是对的。

大概说有效的点是\(O(m)\)个,两两配对进行记忆化有\(O(m^2)\)种。在找的过程中把当前的状态分成子状态最多需要\(O(m)\)时间(可能还不用?)


6952. 【2020.01.16冬令营模拟】吞天得手

反正是字典序所以可以直接递归找。具体:当前存某个状态的集合,表示这些状态当前得到的序列相同,往后转移的时候枚举后继,然后每个状态都尝试转移过去,继续递归。后继可以用主席树维护。因为爆栈所以70分了。

ll说C_C说这东西是A*。搞普通的A*的过程每次扩展出的状态比较多会TLE,那每次就扩展少量的状态。具体是从优先队列中取出第一个,扩展它的最优的后继,以及它的“兄弟”(它的前驱扩展了它,再扩展下一个,但在这之前下一个还没有加入优先队列中)。


6964. 【2020.01.24冬令营模拟】台

通解(不需要加特殊的限制):显然可以DP设\(f_{i,j}\)表示处理前\(i\)个,最后一个为\(j\)的最小代价。考虑优化这个东西:分成两步,第一步\(f_{i,j}\to f_{i+1,k},k\in[j-d,j+d]\),第二步\(f_{i+1,k}\)加上\(|h_{i+1}-k|a_{i+1}\)(相当于以\(h_{i+1}\)为顶点加个"V"形)。

可以发现这是下凸壳,差分数组递增。维护差分数组。第一步相当于找到最低点,最低点往两边各拉伸\(d\)格,其它相对顺序不变;也就是找到差分数组正负交界处,插入\(2d\)\(0\)。第二步相当于在\((-\infty,h_{i+1}]\)整体减,\((h_{i+1},+\infty)\)整体加。用splay维护即可。

基于特殊限制的题解做法表示不会,但也说下:差分\(h\),一次操作相当于给\(h_i\)加一,\(h_{i+1}\)减一(或反之)。如果把\(h_i\)看成物品,那么对于一段区间进行同样的操作相当于把一个物品移到另一个位置,代价是区间的\(a_i\)和。给\(a_i\)前缀和,看作坐标,于是变成了:

  1. 如果\(h_i>d\),则相当于有\(h_i-d\)只必须转移的老鼠和\(2d\)只没有要求的老鼠。
  2. 如果\(h_i\in[-d,d]\),则相当于\(h_i+d\)只没有要求的老鼠和\(d-h_i\)个没有要求的洞。
  3. 如果\(h_i<d\),则相当于有\(d-h_i\)个必须被转移到的洞和\(2d\)个没有要求的洞。

据说这是经典的老鼠进洞问题,可以模拟费用流解决。(但是时间复杂度似乎被通解爆标了呢)

这里我就不会啦。


LOJ2525. 「HAOI2018」字串覆盖(口胡)

~~洛谷和LOJ的描述不一样导致我对着一道魔改过的神仙题想了半天只有2030分。~

为了方便下面\(n,q\)不区分。

容易想到把\(r-l+1\le 50\)\(r-l+1\ge 2000\)分开做。

对于后者,建出SAM,用线段树合并处理出\(right\)集合。在对应的区间中找第一个子串,暴力往后跳继续找。最坏情况下总时间\(O(50n\lg n)\)

对于前者,可以把\(len=r-l+1\)相同的一起做。处理出原串中所有长度为\(len\)的子串的哈希值,以及询问串的哈希值,按照哈希值为第一关键字,位置为第二关键字排序,就可以把哈希值对应起来了。处理同一个哈希值的时候:对于一个子串求出后面最近的和它不相交的字符串;对于询问先二分出左端点的位置,然后倍增地往后面跳。这一部分总时间\(O(50n\lg n)\)

表示想不出来\(len\in(50,2000)\)该怎么做(虽然说想出了个\(O(n\lg^3 n)\)的对于所有长度都适用的做法但是这个复杂度与\(q\)无关。具体是直接dsu on tree+线段树套树状数组。)

翻翻题解:和\(len\ge 2000\)的用同样的方法做即可。因为不会很多而且随机分布,所以不会很慢。

我:……


CF1129E Legendary Tree

之前某道模拟赛的题的究极弱化版。然而因为思路歪了导致搞了半天。

把操作阉割成:操作1,询问以\(x\)为根\(y\)的子树大小;操作2,询问以\(x\)为根有\(y\)子树内有\(S\)中多少个点。

先求出所有点的子树大小,按照子树大小从小往大加入。每次二分出它的儿子即可。于是操作次数不超过\(n+n\lg n\),后面这个\(\lg n\)甚至跑不满。而且可以搞一些剪枝。

之前那题:操作1,询问以\(x\)为根\(y\)的子树大小;操作2,询问以\(x\)为根\(y\)子树内完全包含或部分包含或不包含\(S\)的点。其中一档部分分只能用操作2,那题的做法是随便一个点,然后二分出它子树中的所有点,分成两个连通块继续做下去。因为操作2返回三种状态,根据这个可以把二分优化成\(\min(a,n-a)\lg n\)次,其中\(a\)为这个子树大小。于是那样做相当于启发式合并的时间复杂度。


CF1158E. Strange device

两个部分:求出到\(1\)距离相同的点的集合,以及处理出每个点的父亲。

第一部分:分治一层一层求,对于一层,有一些深度的点已经被确定,并且也确定出其它点在哪个区间。可以通过询问\(d\)\(d-1\)来得到距离小于\(d\)的有哪些、恰好为\(d\)的有哪些。对于一层的若干个区间,按奇数和偶数顺序分开做。注意只处理后代,不要处理祖先,因为有的点可能没有后代不会被处理到。于是这部分次数是\(4\lg n\)

第二部分:对于某一深度,通过二进制询问,于是可以处理出下一个深度的点的父亲是什么。为了不互相影响,模\(3\)一样的深度一起做。这部分次数是\(3\lg n\)


CF1392F Omkar and Landslide

让我想起了这道题:https://www.cnblogs.com/jz-597/p/13751532.html

可以感受到可以把原来先枚举时间再枚举位置,变成先枚举位置再枚举时间。

增量搞,每加入一个数就维护一下。用栈维护若干个等差数列即可。


CF1392G Omkar and Pies

\(count(s,t)\)为两个串相同位置的个数。显然如果对\(s\)\(t\)做同样的变换,\(count\)是不变的。

\(o_i\)表示第\(i\)个置换,题目相当于找到\([l,r]\),贡献为\(count(so_lo_{l+1}\dots o_{r},t)\),可以换成\(count(so_lo_{l+1}\dots o_{n},to_{r+1}\dots o_{n})\)

预处理两者,现在得到了一坨串\(a_i,b_i\)。考虑如果相同的\(1\)的个数是\(z\),在其中一个串中的\(1\)的个数分别是\(x,y\),那么贡献是\((k-x-y+z)+z\),只需要最大化\(z\)

枚举\(a_i,b_j\)的交集\(S\),预处理出最小的\(i\)满足\(S\subseteq a_i\)\(j\)同理。

时间\(O(nk+2^kk)\)


Codeforces Round #698 (Div. 1)A~C

A:发现能得到的是和\(a_1\)差值为\(\gcd(a_1,\dots,a_n)\)的倍数的数字。

B:倒推,决策是唯一的。

C:假如某个排列中有个钝角,那么交换一下钝角所在的点和它左边的点。发现这时候这个点的钝角一定消失,但可能移到右边的点。继续往右边调整,最终钝角会消失。于是从后往前扫,见到一个钝角就做上述调整。\(O(n^2)\)


6977. 【2021.02.02冬令营模拟】去南极

题解做法解微分方程,讲题时人人高等数学大师就我一个不会微积分。

阳间做法:首先可以搞出个\(O(n^2)\)DP,显然可以前缀和优化成\(O(n)\),然后变成矩阵乘法。

主要矛盾是处理区间修改。

首先每个区间加操作是满足分配律的(就是说可以分开统计之后加在一起)。先处理出个\(s_i=1\)的区间矩阵乘积,发现当\(s_i\)整体从\(1\)变成\(x\)时,矩阵中的几个位置乘\(x\),其它位置不变。于是在线段树中维护个当前的区间矩阵乘积和\(s_i=1\)的区间矩阵乘积,区间修改的时候就把\(s_i=1\)的区间矩阵乘积中特定几个位置乘\(x\)加到区间矩阵乘积上。

矩阵只需要存\(3*3\),并且由于有\(3\)个位置值是固定的分别为\(0,0,1\),如果想优化的话矩阵乘法的复杂度也不高。并且也可以写标记永久化。

时间\(O(n\lg n*矩阵乘法复杂度)\)


6978. 【2021.02.02冬令营模拟】登山(口胡)

\(type=0\):枚举高度不超过\(h\),考虑用所有的减去高度超过\(h\)的,列出式子。根据式子的性质进行一些推理,最后主要矛盾为:求\(F(m,n)=\sum_{i=0}^n\binom{m}{i}\),由于可以\(O(1)\)变换到\(F(m\pm1,n\pm1)\),所以可以莫队搞它。

\(type=1\):枚举高度\(h\),问从\((0,0)\)\((n,0)\)每次往斜上方或斜下方走一格,要求不经过\(y=-1\)\(y=h+1\)的方案数。可以容斥解决:设两个边界为\(A,B\),方案为\(所有-经过A-经过B+经过AB+经过BA-经过ABA-经过BAB+\dots\)。经过一个边界的时候,可以视作将起点沿着这个边界对称的一下。于是可以推出式子(然而似乎不是很直观呢,所以都是抄题解):

\[2m=n \\ g(h)=\binom{2m}{m}-\binom{2m}{m+1}-\binom{2m}{m+h+1}+2\binom{2m}{m+h+2}-\binom{2m}{m+h+3}+\dots \]

实际上就是

\[g(h)=\binom{2m}{m}-\binom{2m}{m+1}+\sum_{k,x=m+k(h+2)}2\binom{2m}{x}-\binom{2m}{x-1}-\binom{2m}{x+1} \]

最终答案为

\[ans=\sum_{i\ge 1}i(g_i-g_{i-1})=mx*g_{mx}-\sum_{i=0}^{mx-1} g_i \]

由于\(mx*g_{mx}\)\(g_i\)中的\(\binom{2m}{m}-\binom{2m}{m+1}\)抵消,所以答案为\(\sum_{i=0}^{mx-1}\sum_{k,x=m+k(i+2)}v_x\)\(v_x\)为其贡献。算出\(v_x\)的系数,可以发现实际上就是\((i+2)|(x-m)\)\(i\)的个数,相当于因数个数。可以线筛求得。


6979. 【2021.02.03冬令营模拟】天各一方

根据最短路分层DP。可以写出个\(f_{i,j,k}\)表示考虑距离为\(i\)以内的点,已经用了\(j\)个点,距离恰好为\(k\)的点有多少个。统计答案的时候枚举距离,计算距离大于等于这个的方案有多少个,那么\(f_{i,j,k}\)的贡献为:大小为\(j\)的连通块和\(n-j\)个点之间连边,其中大小为\(j\)的连通块有\(k\)个接口,这样形成的连通图的方案数。可以用\(O(n^3)\)的时间内容斥处理\(g_{k,n-j}\)表示这个东西。

写出\(O(n^4)\)的时候发现统计答案的时候和\(i\)没有关系,只是单纯地叠加。所以把\(i\)省掉就可以\(O(n^3)\)了。


6981. 【2021.02.03冬令营模拟】在星河里

先考虑\(n\)为奇数。用点简单的生成函数技巧可以得出个\(O(nm)\)的做法,瓶颈在于对于每个点的子树(设大小为\(s\)),都要计算\(\sum_{j=0}^{\frac{m}{2}}\binom{j+s-1}{s-1}\binom{m-j+n-s-1}{n-s-1}\)

考虑组合意义:\(m+n-2\)个球选\(n-2\)个,枚举\(j\),前\(j+s-1\)个中选\(s-1\)个。考虑在\(j+s-1\)后加一个球,于是变成了\(m+n-1\)个球选\(n-1\)个,要求第\(s\)个在前\(\frac{m}{2}+s\)的位置;这等价于有\(m\)个球,放入\(n-1\)个隔板,要求前\(s\)个隔板在第\(\frac{m}{2}+1\)个球之前,换句话说就是第\(\frac{m}{2}+1\)个球之前至少有\(s\)个隔板。

按照这个组合意义列式子,需要枚举恰好有多少个隔板。计算恰好的时候可以\(O(1)\)算。所以算了恰好之后后缀和即可。

现在考虑\(n\)为偶数,需要去重。点分治,对于两个点\(u,v\)它们要减去\(w_uw_v(s_u+s_v-s_{rt}-\min(b_u,b_v))\),其中\(w_u\)\(u\)子树和为\(\frac{m}{2}\),并且\(u\)的儿子子树和不为\(\frac{m}{2}\)的方案数,\(b_u\)表示\(u\)到根的路径上的最小值,\(s_u\)为到根路径上的和。

按照\(b_u\)进行排序计算,这样朴素实现可以\(O(n\lg^2n)\);也可以一开始搞一个单调递增的点序列,在点分治的时候按顺序传到每个子连通块中,于是得到了每个连通块的点的顺序排列。按照这个顺序扫,当前点\(x\)中的子树中未遍历过的点的\(b\)都是\(x\),这样就省去了排序的复杂度。理论上是\(O(n\lg n)\)


6980. 【2021.02.03冬令营模拟】你的世界

阴间做法一抓一大把

还是题解阳间:

假如只能操作行和列,那么最终形成的图是网格状的,严谨的表述:对于任意的\(2*2\)的子矩阵,异或和为\(0\)

于是影响到这个子矩阵的只有分别经过四个点的四条对角线。同方向的两个对角线可以差分,于是变成了两组不同方向的对角线的关系。

把这些关系用并查集维护,如果没有出现矛盾就一定有解。


6991. 2021.2.20【2021省赛模拟】仲夏夜跑步

考虑求\(f_n\)表示长度为\(n\)的震荡序列(小大小大……)个数。定义反震荡序列(大小大小……),发现两者之间一一对应。

可以得出式子\(2f_{n+1}=\sum_{i=0}^n\binom{n}{i}f_if_{n-i}\),意思是对于所有\(n+1\)的震荡序列和反震荡序列的个数之和,枚举\(1\)所在的位置,左边有\(i\)个右边有\(n-i\)个。

\(F\)\(f\)\(EGF\)。可以列出微分方程\(2F'=F^2+1\)。解之。

\[\frac{2dF}{dx}=F^2+1\\ \frac{2dF}{F^2+1}=dx\\ \int \frac{2dF}{F^2+1}=x+C\\ 2\arctan(F)=x+C\\ F=\tan(\frac{x+C}{2}) \]

带入\(x=0\),此时只有\([x^0]\)有值,应该为\(1\)。所以\(C\)\(\frac{\pi}{2}\)

整理得\(F=\frac{1+\sin x}{\cos x}\)

多项式求逆即可。


CF1336F Journey(口胡)

主要分两条路径\(LCA\)是否相同讨论。如果不相同就是下图情况,按照\(LCA\)深度从大到小做,在深度较大的那个\(LCA\)(如图中\(B\)点),求出往下的两个距离为\(k\)的位置(图中\(C,D\)),分别做子树加;在深度较小的那个\(LCA\)(图中\(A\)点),询问路径两端(图中\(E,F\))的值。

如果\(LCA\)相同,分开两种情况讨论。以下默认路径\((x,y)\)满足\(dfn_x<dfn_y\)

设其\(LCA\)\(X\)。左图中路径交为\((LCA(y1,x2),X)\)。右图中路径交为\((LCA(x1,x2),LCA(y1,y2))\)

左图可以用类似上一种情况的方法计算。具体来说,再将路径按照\(dfn_x\)排序来做,修改的时候只对\(X\to y\)方向的距离为\(k\)的点做子树加,查询的时候只查\(x\)的值。

右图:把\(LCA\)\(X\)的路径的所有\(x\)拿出来建虚树,并把\(y\)挂在对应的\(x\)上。在\(a=LCA(x1,x2)\)处(如图\(A\)点),找到\(a\to y_1\)上距离为\(k\)的点\(p\),问\(a\to p\)方向上\(p\)的子树中\(y2\)的个数;于是可以启发式合并,具体就是每个点维护\(x\)在子树内的路径有哪些,以及维护线段树表示树上\(y\)的分布,启发式合并,小的那边扫一遍找\(p\)然后在大的那边线段树中查询。

好像也可以不用虚树:

遍历的过程中分别维护每个\(X\)的信息,合并两块信息的时候,如果两块有共同的\(X\)就需要进行上面的操作。如果要快速知道两块有哪些共同的\(X\),可以直接开个线段树表示是否有某个\(X\)的信息,然后线段树合并。时间\(O(m\lg n)\)

由于只需要知道有哪些共同的\(X\),不必重构每个\(X\)的信息。所以也可以dsu on tree处理出共同的\(X\)。时间\(O(m\lg^2 n)\)

都不影响最终的时间复杂度。

时间\(O(m\lg^2 m)\)


CF1486F Pairs of Paths(口胡)

题面和上面那题有点像不过方法差了太多。

题目求路径交恰好为一个点,考虑求出至少交为多少,然后容斥一下。

可以发现容斥系数\(f(1)=1,f(2)=-2,f(3)=1\)其它都为\(0\)

经过同一个点和经过同一条边的随便求。经过同两条边的,如果路径交为祖先后代,可以在每个点\(x\)记录一下穿过\(x,fa_{fa_x}\)的边的个数,稍微差分一下可以得到;否则中点为\(LCA\),直接在\(LCA\)处统计。

时间\(O(m\lg m)\)(或\(O(m)\)?)


【UER #9】赶路

方法多种然而自己一个都不会。

题解做法:考虑一种方法是从起点开始,以终点所在方向为分界线,极角排序。在出现相邻相差180度以上的时候会挂掉。这种情况下起点一定在凸包上,于是找到凸包上相邻的两个点,连向其中一个(如果其中一个是终点要判一下),然后变成子问题。由于剩下的点集的边不会超过这个点集所组成的凸包,所以不会有交。时间\(O(n^2)\)

隔壁神仙做法:前半部分和上面一样。起点和终点都先判一下是否能直接极角排序做,如果不能,那么可以找到两条分别过两点的直线,其它点都在直线的一边;如果直线有交,直接在直线的交点处极角排序;如果直线无交,旋转之使得直线垂直于y轴,然后按照x轴排序即可。时间\(O(n\lg n)\)

uoj群友简单做法:每次随便找个点\(i\),把直线\(1\to i\)左右的点分成两个点集,变成子问题\((1,i,S_0),(i,n,S_1)\)分治下去。如果这个点的取值是随机的,则可以用快排的时间复杂度分析,也是\(O(n\lg n)\)


【UER #9】知识网络(口胡)

注意到从某个点开始,到某个相同颜色的点的集合的距离的极差不超过\(1\)

对于每个颜色分别做,首先从这个颜色的所有点开始跑个最短路,求出到其它的点的最短距离\(f_x\)。接下来要计算有多少个点到\(x\)的距离是\(f_x\),其它的是\(f_x+1\)。建最短路图,就变成了DAG上有多个源点,求每个点能被多少个源点到达的问题。用bitset维护之。注意要自己手写bitset节省空间,可以开得下。

具体实现的时候可以直接宽搜。


【UER #9】面试

首先问\((0,0,0)\)得到\(s=a+b+c\)

如果\(s>\frac{3n}{2}\),则可以把\(a,b,c\)换成\(n-a,n-b,n-c\)。所以只考虑\(s\le \frac{3n}{2}\)

如果\(s\le n\),则问\((0,0,n)\)\((0,n,0)\)可以分别得到\(c\)\(b\)

如果\(s>n\):问\((n,s-n,0)\),得到\(2t=n-a+c+|n-a-c|\)。于是有\(t=\max(c,n-a)\)

分类讨论:如果\(s-t>n\),则问\((n,s-t-n,t)\),得到\(2t+2n-2a-2c\),也就可以得到\(a+c\)。如果\(s-t\le n\),则问\((s-t,0,t)\),得到\(2b\),也可以得到\(a+c\)。通过\(a+c\)\(n\)的大小关系,得到\(t\)具体为多少从而得到\(a\)\(c\)


CF1158F Density of subarrays(口胡)

对于一个字符串,如果密度为\(p\),那么可以找到最短的前驱满足密度为\(p-1\),字符串去掉此前驱之后密度一定为\(1\)。归纳一下,可以发现如果密度不小于\(p\),当且仅当字符串可以分成\(p\)段,使得每段中所有字符都出现过。

\(f_{i,j}\)表示考虑了前\(i\)个位置,密度恰好为\(j\)的方案数,其中最后一个选的位置是\(i\)。转移时枚举\(k\),要求\((i,k)\)中除了\(a_k\)外的所有字符各出现一次,\(a_k\)不出现。可以发现这样时间是\(O(\frac{n^3}{m})\)\(m\)为字符集。

\(m\)比较小的时候回TLE,查题解说\(m\le lg_n\)的时候写状压DP,时间是\(O(\frac{n^2}{m}2^m)\)。两个方法综合起来时间是\(O(\frac{n^3}{\lg n})\)

为什么这能过我感到很奇怪。


Codeforces Global Round 13 C,D,E,G,H

C:发现每次从\(1\)开始操作一定是最优的。模拟即可。用并查集维护连续一段\(1\)\(O(1)\)跳过整段。如果某条路径是\(1,1,1,1,\dots,v\)\(v\)为某个很大的值,这时候可以直接把\(v\)调成\(O(n)\)范围。总时间\(O(n^2)\)

D:比赛时搞了几个贪心拍着拍着就过了。首先可以发现每次操作可以拆成多个,从高位到低位搞。转化成有两种操作:把一个\(1\)左移(如果下一位为\(0\));找到连续的若干个\(1\),把最高位以外的\(1\)变成\(0\),把最高位的那个\(1\)左移。基于此设计贪心。

E:比赛时写了个假做法没有hacked怎么回事啊。考虑对于一棵大小为\(F_k\)的树,找到能将其分为两棵子树大小分别为\(F_{k-1},F_{k-2}\)的边。因为\(F_k=2F_{k-2}+F_{k-3}<3F_{k-2}\),所以这样的边最多有两条。以下证明,如果合法,割掉任意一条都可以得到两棵合法的子树。归纳,如果存在解,解在此时割了边\(u\)。在这个解中,\(v\)所在那个连通块的子问题中,可以割\(v\),由结论可得成立;如果先割了\(v\)。由之前的解分析得\(v\)割出那个子树一定合法,此时\(u\)所在那棵子树大小为\(F_{k-1}\),恰好也可以割\(u\),由之前的解得\(u\)割出的子树也合法。于是得证。

G:做一点普通的图论转化显得直观一些,连边\((p_i,i)\),一次操作相当于把\(p^{-1}_x,p^{-1}_y\)的出边交换,并在\(p^{-1}_x,p^{-1}_y\)\(-1\)标记。发现当一个环中如果有两个\(-1\)标记,那么这个环是可以搞定的;进而发现如果将两个环合并会多两个\(-1\)标记,于是如果环数为偶数就可以两两合并之后搞定它,总次数是\(\frac{c}{2}+n-\frac{c}{2}\)。如果环数为奇数,照样两两处理,对于多出来的那个环,它可以和前面的一个自环合并,一样地搞,次数为\(\frac{c-1}{2}+1+n+1-\frac{c+1}{2}\);如果整个图只有一个环,随便找个点\(x\)\(y=p^{-1}_x,z=p^{-1}_y\),分别给\(x,y\)\(x,z\)进行交换出边操作,此时环满足条件,次数\(2+n-1\)

H:分块。对于一个点\(x\),设\(f_x\)为他的最远的和\(x\)同块的祖先。如果\(a_x\)在块外,则\(f_x=x\),此时\(x-a_x\ge \sqrt n\)。因此如果块中所有点\(x\)都满足\(x-a_x\ge \sqrt n\),则不会再更新。修改操作,对于散块暴力做,次数\(O(q)\),对于整块,由于\(tag\)最多会增加\(\sqrt n\)次,总更新块的次数为\(O(\sqrt n\sqrt n)\)的。一次更新\(O(\sqrt n)\),所以总时间\(O((n+q)\sqrt n)\)


CF1494F Delete The Edges

发现如果有解,路径就是一段欧拉路径接上个菊花图。

枚举菊花图的中点\(c\),对于其它的点\(i\),如果其度数为奇数,如果\((i,c)\in E\)则删去这条边;否则记下这样的点到\(S\)集。如果\(|S|>1\),则无解。

判断下连通性,如果不满足连通性,则尝试调整把之前删去的边加回来。

时间\(O(nm)\)


6996. 2021.03.06【2021省赛模拟】计数(口胡)

\(n\)\(9\),于是变成了\(\sum \lfloor\frac{n}{10^i-1}\rfloor\)

拿出计算器发现\(\frac{1}{10^i-1}\)是非常有规律的,比如\(\frac{1}{99}=0.010101\dots\)

列出竖式,玩一下得出:\(\lfloor\frac{n}{10^i-1}\rfloor=\lfloor\frac{n}{10^i}\rfloor+\lfloor\frac{n}{10^{2i}}\rfloor+\lfloor\frac{n}{10^{3i}}\rfloor+\dots+t\)

其中\(t\)为其中的每一项的余数除以\(10^i-1\)的结果。

先不考虑\(t\),相当于加上一个平移多少位的数。这样的操作有\(\sum \frac{n}{i}=O(n\lg n)\)个,全部压起来然后一发FFT搞定。

至于处理余数:因为数据随机,所以不要求太大的精度。直接用long double强行算出。

时间\(O(l\lg l)\)


AGC052 ABD

A:

显然可以做到\(n\)\(0/1\)\(n\)\(0/1\)拼在一起得到\(2n\)长度的答案,考虑插入一位。考虑分界线上的情况(即三个字符串最后一位),如果相同显然可以;如果不同(假设为\((1,1,0)\)),那么可以\(n\)\(0\)\(n\)\(1\)\(1\)\(0\)。可以视作把字符串分成三个

部分,对于最后为\(1\)的那一行,左边连续的一段\(1\)的后缀不参与第一段的贡献,参与第二段的贡献;右边这段后缀不参与第二段的贡献,刚好和前面补齐;这时候一定能空出\(0\)出来。

B:

定根,为了方便钦定\(rt\)为叶子。然后做前缀和\(s_i\)。如果操作\((x,rt)\),则是对所有\(i\neq x,i\neq rt\)\(s_i\leftarrow s_i \ xor \ s_x\)。如果操作\((x,y),y\neq rt\),则是对\(i\in\{x,y\}\)\(s_i\leftarrow s_x\ xor \ s_y\)

可以转化为:有\(n-1\)个数,支持交换,和选择一个数让其它数异或这个数。把它视作集合忽略交换,对于后者,手玩一下(比如\(x_1,x_2,x_3\)),可以发现要么是原样,要么是\(x_1,x_1\ xor \ x_2,x_1\ xor \ x_3\)的形式,如果下一步不选择\(x_1\)也没有办法让它更复杂。

由于\(2|n-1\),所以根据两次异或和的变化量可以得到\(x_1\),然后判定。

D:

\(f_i\)为以\(i\)为结尾的LIS长度。按照\(f_i\)分层。

设总的LIS为\(L\),如果\(L\)为偶数,设\(L=2k\),则可以给两个子序列各分配\(k\)个整层,于是每个子序列的LIS长度为\(k\);如果\(L=2k+1\),由于总序列的LIS长度小于等于两个子序列的LIS长度之和,所以子序列LIS长度至少为\(k+1\)

两个子序列的LIS有\(2k+2\)个东西,至少有个东西不在原来的LIS中。设这个东西为\(x\),它一定要被一个长度为\(k+1\)的上升子序列包含。

证明其充分性:构造,设这个子序列为\(i_1,i_2,\dots,i_{k+1}\),对于\(f_i\notin\{f_{i_1},\dots,f_{i_{k+1}}\}\)\(i\),把它丢入第一个子序列;对于\(f_i=f_x,x\neq i\)\(i\),把它丢入第一个子序列;其它丢入第二个子序列。发现此时两个子序列的LIS一定恰好都是\(k+1\)

判定:求\(f_i,g_i\)\(g_i\)为从\(i\)开头的LIS长度),如果\(f_i+g_i\ge k+2\)的点大于\(2k+1\)则合法。

E:

\(A,B,C\)分别为\(0,1,2\)。构造序列\(A\),满足\(|A_i-A_{i+1}|=1,A_i\mod 3=S_i\)。显然如果固定\(A_1\)整个序列都确定了。

一次操作相当于选择一个位置\(\pm2\),要求其仍然满足这个性质。

假如对\(S,T\)分别构造出序列\(A,B\),首先要满足\(A_1\equiv B_1 \pmod 2\),然后把\(A\)变成\(B\)的最少步数是\(\frac{1}{2}\sum |A_i-B_i|\)

证明:显然这是下界。现在只需证明,只要满足性质,一定存在方法使\(\sum|A_i-B_i|\)减少。如果不存在且没有减到\(0\),此时\(A\)一定存在可操作性点\(i\),满足\(A_i\neq B_i\),否则对应字符串形态固定。设\(i,j\)\(A\)中相邻的可操作点,且满足\(A_i\neq B_i\)\(A_j\neq B_j\)。不妨设\(i<j\)\(A_{i-1}<A_i>A_{i+1},A_{j-1}>A_j<A_{j+1}\),此时有\(B_i\ge A_i,B_j\le A_j\)(其它情况类似),则一定有\(\forall k\in[i,j),A_{k}-A_{k+1}=1\),所以\(A_i-A_j=j-i\)。所以\(B_i-B_j>j-i\),由于\([i,j)\)之间相邻点相差为\(\pm 1\),所以一定不合法(可以看做此时斜率绝对值需要大于\(1\))。

最后问题是决定\(B_1\)满足\(B_1=A_1\pmod 2\)且最小化\(\sum |A_i-B_i|\)。先搞一个合法的\(B_1\),然后给\(B\)整体加上\(6x\),其中\(x\)为任意整数。枚举\(x\),稍微维护一下就可以\(O(n)\)做。


6998. 2021.03.08【2021省赛模拟】序列

显然当贡献固定时,和要最大。分开每段考虑,每段要么全选,要么压住上限。

\(f_{i,j}\)表示考虑了\(i\)段,贡献为\(j\)时的最大和。转移:全选很好做;另一种转移可以贪心,维护个堆表示最大值,从前往后扫,扫过的元素丢入堆中,尽量不选,直到到了负数,这时候在堆中取出最大值。然后继续做。如果扫完了,剩下的贪心选。


6999. 2021.03.08【2021省赛模拟】递推

题目中的式子显然是复数乘法。于是\(A_n+B_ni=(x+yi)^n\)

因为\((a+bi)^2+(b+ai)^2=4iab\),根据这个东西可以把答案拆成两个等比数列求和。

如果公比的模长小于\(1\),则无限时收敛。

最恶心的地方是\(c\equiv 0\pmod p\)的情况。题解说如果\(p\)满足\(p\in P,p\equiv 3\pmod 4\)(即\(p\)是高斯素数),特判掉\(xy=0\),则不会出现无法求逆的情况。

对于这部分,我是用另外两个素数计算一下判断是否为0水过的。


7001. 2021.03.09【2021省赛模拟】续命大战

考虑只有奇数的情况。发现答案是和的奇偶性。如果进行操作1,后手也可以跟着操作\(1\)保持奇偶性不变;如果进行操作2,后手操作那个偶数,也保持奇偶性不变。

只有偶数:操作偶数不会影响奇数的和的奇偶性,也不会影响其他偶数,所以可以分成个子问题。算一下发现\(i\)\(sg\)函数是:若\(a_i\mod (i+1)=i\),则为\(2\),否则为\(a_i\mod (i+2)\mod 2\)

奇数的\(sg\)函数为和的奇偶性。于是把奇数和所有偶数的\(sg\)异或起来就行了。


7000. 2021.03.08【2021省赛模拟】统计(口胡)

树分块。(我想的是王室联邦分块法)

块之间连成了个树形结构。在处理某个块时,处理好祖先链上的哈希表,以及每个儿子块的子树的哈希表。\(x,y,z\)至少有两个在同一块内的情况很好算。现在考虑只有\(y\)在块内的情况:把每个儿子块的子树的哈希表分别和祖先链FFT,然后块顶和儿子块之间的点可以作为\(y\)统计到。

由于每个块子树只有一次作为儿子出现,所以只会被FFT一次。这一部分时间\(O(km\lg m)\)\(k\)为块大小。

前面暴力时间\(O(\frac{n^2}{k})\)

平衡规划即可。


AGC051

A:

显然内角需要用一个正方形和一个三角形拼接。从外面一层一层往里面包。\(f(n,m)\)表示要包个奇数边为\(n\),偶数边为\(m\)的方案数。根据奇数边用正方形还是三角形,手玩一下下一层是什么,可以得到转移:\(f(n,m)=f(n-1,m)+f(n,m-1)\)。由于最外层不区分奇偶边,所以答案减半。组合数计算即可。

B:

随机三个向量\(p=(a,0),q=(0,b),r=(c,c)\),然后构造点集:\(\{ip+jq+kr|i,j,k\in[0,10)\}\)

比如\(A\)看到的只和\(q,r\)有关,所以最多\(100\)个。然而\(D\)和三者都有关,最多\(1000\)个。

随机情况下大概率不会出现重复。


Codeforces Round #706 (Div. 1)

A:把点对称到正半轴上,发现连线相交显然不优,按顺序匹配。

B:

我的做法:对于\(x\)分别计算,对于\(y\)考虑它是否和\(x\)互相干涉,粗略讨论之后直接数据结构维护。

正常做法:对整体进行一些细致的分析,分类讨论即可。

C:

每三行填满,然后把填满的几行连一下,特殊处理下最后一行。

D:

先求出两两间最短路。\(x,y\)之间最短路只有一条否则无解。把\(x,y\)之间的最短路拉出来作为一条链,之后把每个点分到链上节点的子树中做。稍微判一下它是否能在这个子树内。


CF1054H Epic Convolution

模数很小,于是统计\(i^2j^3\mod (p-1)\)相同的贡献。可以把\(i^2j^3\)拆开成\(\binom{i^2+j^3}{2}-\binom{i^2}{2}-\binom{j^2}{2}\),然后就可以卷积了。

卷积的时候用\(29*2^{57}+1\)作为模数,当然也可以FFT。

题解做法:\(490019-1=2*491*499\),考虑CRT合并。

相当于求\(S_{x,y,z}\sum_{i}A_i\sum_j B_j [i^2j^3\equiv x\pmod 2][i^2j^3\equiv y\pmod {491}][i^2j^2\equiv z\pmod {499}]\)

第一维随便搞,后面两维找出原根,然后二维FFT。


5674. 【GDOI2018Day1模拟4.20】香槟(口胡)

\(k=0\)时,Bob能获胜当且仅当\(n=2\)

\(k>0\)时,如果\(n\)为奇数则Alan必胜。

\(n\)为偶数时,对于Alan来说,如果能找到个点,这个点把图分成两个以上(实际上至少三个)的奇连通块,那么Alan必胜。显然如果能分成两个以上奇连通块,则没有完美匹配。如果不能分成两个奇连通块,则有完美匹配,归纳证明:可以选择一个最深的叶子节点和父亲匹配,它的父亲没有其它儿子。剩下的连通块仍然不能分成两个奇连通块。

所以如果不存在完美匹配,则Alan必胜。如果存在,Alan可以强制每次选完美匹配中的一个匹配,并且这时候Bob一定要切边否则不优。所以如果此时\(k<\frac{n}{2}-1\),则Alan必胜。

\(k\ge \frac{n}{2}-1\)时,Bob只要一开始把图分成若干个大小为\(2\)的连通块,就能必胜了。


5669. 【GDSOI2018模拟4.19】排列

如果决定了最大子段和,则对于每一条路径都可以分成三段。

网络流,\(S\to i_1\to i_2 \to T\),通过割哪条决定哪一段。

如果有边\((u,v)\),则连边\(u_1\to v_1,u_2\to v_2\)。于是\(u\)割的段一定不能在\(v\)割的段后面。

连边的时候根据正负分别连,答案为正权和-最小割。


7008. 2021.03.12【2021省赛模拟】威士忌

固定一维,从高往低扫。剩下两维形成个阶梯。每次求阶梯和一个L形的交。

维护队列,两边往中间删。维护这个交就好了。

可以发现修改的时候也可以两边往中间删,不需要直接在阶梯的中间改。

时间\(O(n)\),排序可以桶排。


7009. 2021.03.13【2021省赛模拟】抽卡

可以算出抽到五星卡的期望步数,然后对于每个\(i\)算当前有\(i\)个五星卡,抽到一个新的五星卡期望要抽多少个五星卡。两者乘起来即可。

最后要求调和级数,打表即可。

表示自己推的时候全程概率生成函数,偶然间发现一个有趣的结论:\(\sum_{j=1}^n\binom{n}{j}(-1)^{j+1}\frac{1}{j}=\sum_{j=1}^n\frac{1}{j}\)


Codeforces Round 707(Div1)

A:排序,现在相当于要找两条等长的线段。直接暴力做有\(O(n^2)\)的做法。如果只考虑相邻点,并且这样考虑没有得到结果,那么大概有\(maxA>O(n^2)\)。于是可以在\(n\le 5000\)的时候暴力,更大的之后只考虑相邻点。

B:

处理出一个循环节的贡献。接下来处理余数的贡献。设\(n<m\),两个数列分别为\(a,b\)。记\(c_i,i\in[0,m)\)表示分别从\(a_0,b_i\)出发走\(n\)步的贡献。由于没有看到题目的限制我写了FFT+平衡规划,如果没有那条限制时间\(O(n\sqrt {n\lg n})\),有那条限制\(O(n)\)(根本不会跑FFT)。有了\(c_i\)之后跳若干次,每次跳\(n\)步,接下来再一步一步跳,时间\(O(n)\)

其实也可以二分答案,然后对于每个\(b_i\)记一下它的贡献。具体就是和它匹配的\(a_j\)会形成一个环,问题相当于求一个环上的区间上有多少个\(b_i\)。离线一下应该可以做到每次\(O(n)\),于是总时间\(O(n\lg k)\)

C:

实际上相当于安排排序的关键字。考虑对\(b\)划分。维护若干段,每段由若干行组成。一开始只有一段。每次选择一列,要求每段的这一列是有序的,然后根据这一列的值继续将其划分成若干段。模拟即可,无脑实现\(O(n^3)\),加点脑子维护\(f_{i,j}\)表示列上以\((i,j)\)结尾的最长的不下降子段,于是可以快速维护出每段中每列是否已经有序,时间\(O(n^2)\)

D:

考虑枚举格子\((i,j)\),维护极大的合法正方形边长\(k\)。显然从\((i,j)\to (i,j+1)\)时,\(k’\ge k-1\)。如果能快速地维护是否能扩展,那么时间就是\(O(n^2*维护时间)\)了。

考虑怎么维护:我们需要快速找出一行的某个区间的所有值的出现次数。只需要保留\(q\)个值,否则这段区间不合法。对于一个位置\(j\),维护以它结尾的最长合法后缀,以及这个后缀中出现了哪些数。

然而我们需要知道一段区间的值的出现次数,直接前缀和不行。考虑从左到右扫过来,设当前扫到位置为\(j\),这个最长合法后缀为\([k,j]\)。维护个集合表示至多\(q\)个数,维护个数组\(sum_i\)表示\(i\)从上一次进入集合开始的出现次数。每次加入一个数\(x\),对应\(sum_x\)加一,并且为了保持集合表示至多\(q\)个数移动\(k\)。如果某个数从集合中删去,则对应\(sum_i\)清空。此时如果要询问一段合法区间每个数的出现次数,首先值都是右端点所维护集合里的值,如果这个值也在左端点中,而且从左端点扫到右端点的过程中这个值从未在集合删去,则两者出现次数作差,否则左端点的视为\(0\)

精细实现,总之时间复杂度\(O(n^2q)\)

E:

排序,枚举大小\(i\),前\(i\)大和与后\(i\)大和形成的区间取并就是答案。

根据前\(i\)大和与后\(i\)大和各自增长的规律,以及它们之间的差分析,容易得出:所得区间一定是若干个独立的子区间+合并起来的大区间(可能不存在)+若干个独立的子区间。

用数据结构维护。每次先判断中间那个大区间不存在,如果不存在直接算,存在就二分出两边的分界点然后算。

其实可以进一步地发现,这个结构是对称的(指区间和其长度,不是位置),所以只需要求出一边。

时间\(O(n\lg^2 n)\)


ARC114

A:指数级暴力即可。

B:显然一个合法的\(T\)为一个环。找环即可。

C:一个数组\(A\)的答案是:n-相同高度的点中相邻的中间没有更低的点的对数。枚举这对点高度和中间长度计算。

D:DP。考虑从左到右扫过去,\(f_{i,j}\)表示到\(i\)点,当前带着\(j\)条线段,\(g_{i,j}\)表示当前借了后面的\(j\)条线段。在点和点之间的转移中不会同时既带着线段又借着线段。在某个点改变线段的状态时,拥有的线段可以任意丢掉,可以从当前点补充有限个;借的线段可以任意借,可以从当前点中还有限个;注意在某个点的时候,可能会发生先把借了的线段还光,再得到若干线段的情况。朴素实现\(O(n^3)\)。可以通过简单优化至\(O(n^2)\)

E:分别考虑每条线被割的概率,加起来之后就是期望割的次数。考虑一个弱化的问题,有\(n\)个点,每次有\(\frac{1}{n}\)的概率丢掉后面\(i\)个点,\(i\in[1,n]\),问某点\(j\)被操作到的概率。发现概率是\(\frac{1}{j}\)。因为\(j\)前面的点等概率被丢,\(j\)是第一个被丢的概率为\(\frac{1}{j}\)。类似考虑这题,注意这样考虑的时候,四个块的线是可以分开考虑的。


7013. 2021.03.15【2021省赛模拟】キ

分治,考虑跨过中间的矩形。假设按列分治,枚举两行,分别计算两边的贡献,然后对应相乘。

细节不说,总之朴素的实现有\(O(n^3)\)

行列轮流分治,时间变成\(O(n^2)\lg n\)


7017. 2021.03.15【2021省赛模拟】B(口胡)

第一问显然是\(奇数度数点个数/2\)。第二问显然可以贪心。至于第三问:设\(f_{i,j}\)表示\(i\)节点中伸出一条链,链已经有的长度为\(j\)

转移:枚举哪个儿子的边伸上去,然后用\(g_s\)表示已经选了\(s\)中的儿子的方案数。转移的时候找到最小的不在\(s\)中的儿子,枚举另一个儿子。于是这一部分枚举次数是\(O(2^DD^2)\)的,其中\(D\)为儿子数。

当把两个儿子\(a,b\)配对时,暴力要算\(\sum_{i}f_{a,i}\sum_{i+j\le lim}f_{b,j}\)。长链剖分,线段树维护\(f\),暴力枚举\(i\)然后区间查询\(\sum f_{b,j}\),配对的时候保证\(len_a\le len_b\),这样有个好处是保证了暴力枚举的一定不是长链。

算完\(s\)之后要把一些\(f_i\)区间乘之后加在一起,这个也可以线段树维护。

由于状态数不多所以可以过?


7016. 2021.03.16【2021省赛模拟】A

考虑每个0的位置与时间关系图像。从后往前扫维护函数\(f(t)\)

\(i\)转移到\(i-1\)时,如果\(s_i=0\),则函数往下平移一格,往右平移一格,并且\(t(0)=i-1\)

如果\(s_i=1\),则找到函数的第一个\(t(j)=t(j+1)\)的位置,然后把\([0,j]\)的函数全往下平移一格。

解释:后一个0动了之后,将要到前一个0动,那么前一个0会延续着后一个0的轨迹。如果后面有个1,那么这个0是可以提前动,但是但是在遇到下一个0的时候回停止。

用栈和队列维护即可。


2021.03.16【2021省赛模拟】C

显然可以问点集中的点是否有些在某个点在某方向的子树内。

随便定个\(rt\)。现在考虑处理出\(x\)的子树。首先二分找到个点\(y\)\(x\)的子树内,然后\(dfs(y)\)。直到找到一个叶子。把它标记为叶子然后删除。

一个点如果变为了叶子,那么它的儿子都已经被标记为叶子,于是可以二分找到它的所有儿子。

次数\(2n\lg n+2n\)


7014. 2021.03.15【2021省赛模拟】丰

先把边倍长。

首先可以感受到只会对叶子节点连的边操作。

假设有直径中点\(c\),叶子的个数为\(l\)。所有叶子到它的距离和为\(s\),那么半径为\(R\)时的容纳操作次数为\(\lfloor\frac{Rl-s}{2}\rfloor\)

\(f_{R}\)表示半径为\(R\)时容纳的操作次数最多为多少。显然\(f_R\to f_{R+2}+l\)

如果要把一个点调成直径中点,需要先对边进行一些调整,使得所有叶子结点到它的距离和大于等于原来叶子节点到它的距离最大值。于是它贡献到的\(f_R\)是有下限的。

因此需要对于每个点求出它们各自作为直径中点的贡献,合并起来。

发现如果\(R>2n\),则只和\(f_{2n-1}\)\(f_{2n}\)有关(根据奇偶性)

求答案的时候,如果小就在\(2n\)范围内二分,否则\(O(1)\)计算。

时间\(O(n+q\lg n)\)


7018. 2021.03.18【2021省赛模拟】光明

首先能想到二分+长链剖分,由于二分值域为\([0,n]\),可以根据递归过程中值被改变的时间,维护出每个值有多少个。于是\(O(n)\)


7019. 2021.03.18【2021省赛模拟】游戏

稍微分类讨论加推式子,得到答案相当于求\(F(L)=[x^n]\frac{m(x-x^{L+1})}{1-mx+(m-1)x^{L+1}}\),表示极长段长小于等于\(L\)的方案数。

写个常系数齐次线性递推,可以得到\(O(L\lg L\lg n)\)的做法。由于模数不是NTT模数所以又要用\(29*2^{57}+1\)(切换模数的时候记得调成非负数)。

\(L\)比较大时,对于\(\frac{1}{1-mx+(m-1)x^{L+1}}\),可以看成\(\frac{1}{1-A}\)的形式展开,再二项式系数展开。由于只需要求\([x^n]\),有效的对数是\(O(\frac{n}{L})\)个,枚举直接算即可。时间\(O(\frac{n}{L}\lg n)\)

两者结合,平衡规划,阈值大概调个\(5000\)就能过了。


2021.03.18【2021省赛模拟】 皇后

随机个排列。记\(cnt\)为矛盾的个数。记下矛盾点有哪些,每次随机交换两个位置,要求至少一个是矛盾点,然后计算\(cnt'\)。如果更小就接受,如果更大以一定概率接受,如果很久都没有减少则重新来一遍。

实测\(4999\)跑4s。


7020. 2021.03.19【2021省赛模拟】圆弧

枚举1的选择情况,拆环成链,然后随便做。

具体一点就是先通过BFS搞出已经确定的匹配,后面的用类似DP的方法计算。


7021. 2021.03.19【2021省赛模拟】整除

猜答案是\(n\)以内的数。首先判掉多项式整除的情况,只有那时候有无限解(如果\(x\)远大于系数则可以看做一个形式幂级数)。

两边乘\(1-x\)。于是要模\(x^m-1\),相当于所有系数贡献到模\(m\)的位置。

先在多项式意义下处理这个东西。当带入点值的时候,对于其中\(a_i\notin(-x,x)\)的位置给它进位。每次进位绝对值之和减去\(x-1\),所以只需要做\(\frac{\sum|a_i|}{x-1}\)

答案是个调和级数,加上用点数据结构优化查找,时间\(O(n\lg^2 n)\)


7022. 2021.03.19【2021省赛模拟】词典

写出递推式:\(f(n)=c(n)+\min(f_k+f_{n-k}+[k>1]c(k))\)

打表发现决策点单调所以可以\(O(n)\)

显然\(c(n)\)是下凸函数。归纳得到\(f(n)\)也是下凸函数(凸函数+凸函数=凸函数,右边\(f_k+c_k\)是凸的,\(min\)中的就是个闵可夫斯基和得到的也是凸的,最后凸的加凸的还是凸的)。

观察发现\(c(n)=O(n\lg n),f(n)=O(n\lg^2 n)\)

\(g(i)\)表示\(f_j-f_{j-1}=i\)的最小\(j\)。需要求\(O(\lg^2 n)\)。求出来之后就可以用\(O(\lg^2 n)\)\(O(\lg\lg^2n)=O(\lg \lg n)\)时间得到\(f(n)\)

于是倍增求\(g(i)\)。当前有个能快速得到的范围\(M\),求出下一个\(g(i)\),在范围\((M,1.5M]\)之间二分。套个三分决策点,表出决策点大于\(\frac{n}{3}\)所以以它作为下界,于是三分时查询的范围就在\(M\)以内。

优秀的实现可以得到\(O(\lg^5n)\)。当然也可以打表。


牛客挑战赛48

A:略

B:把\(i\in[i,n]\)的概率改写成\(i\in [i+1,n]\)就能做了。

C:假设有一种方案,连通块大小为\(a_i\),再加入一些边之后形成生成树的方案数为\(n^{k-2}\prod a_i\),显然有\(\sum_{a_i}n^{k-2}\prod a_i=n^{n-2}\binom{n-1}{m}\)。答案求\(\sum_{a_i}\prod a_i\)

D:直接子集卷积即可。

E:抢一血失败.jpg

我的lj做法:分块套线段树,修改时间\(O(\log V)\),查询时间\(O(\frac{n}{B}\lg n+B)\),平衡规划一下时间复杂度\(O(n\sqrt {n\lg n})\)

诶忽然想起我散块那部分时间是不是打假了啊

高级做法:对序列和值域都分块。对块记个值域的前缀和,修改\(O(\sqrt n)\),查询时先枚举答案在哪一块,可以\(O(\sqrt n)\),然后在这个块中枚举。时间\(O(n\sqrt n)\)

F:枚举平方串的一段的长度\(d\),以\(d\)为周期设个分界点,如果相邻分界点\(LCP+LCS\ge d\),此时就查出了一段平方串。给这段平方串的开头打标记。

G:我的口胡做法:整除分块,相当于对于所有\(\lfloor\frac{n}{i}\rfloor\)求前缀和。因为要取模分组,把系数换成\(x^{c_i}\)\(x\)带入30个点值,高斯消元一下就出来了。然而我不会min25的这种高级做法2333。

正解做法:先改写成\(\sum_i \sum_{d|i}[c(d)\mod k=r]\),后面那个东西是个积性函数。

把后面那个东西写成\(\sum_{d|i}x^{c(d)}\)。于是积性函数\(f(p^c)=\sum_{i=0}^cx^i\),跑一遍普通min25筛即可。


6082. 【GDOI2019模拟2019.3.25】染色问题(口胡)

首先可以得到递推式:\(f(n,m)=f(n,m-1)+\sum_{i=0}^{n-1}f(i,m-1)(i+1)\)

\(G_n\)表示其生成函数(不要设\(F_m\),那样得到\(F_m(x)=\frac{x^2}{1-x}F'_{m-1}+\frac{1}{1-x}F_{m-1}\),没规律):

\[G_n(x)=\sum_{i=0}^{n-1}G_{i}(x)(i+1)x+G_n(x)x\\ G_0(x)=1\\ G_n(x)=\frac{1}{1-x}\sum_{i=0}^{n-1}G_i(x)(i+1)x\\ G_n(x)=G_{n-1}(x)+\frac{1}{1-x}G_{n-1}(x)nx\ (n\ge 2)\\ G_n(x)=\frac{\prod_{i=1}^{n-1}(1+ix)}{(1-x)^n} \]

上面的部分可以倍增计算。设当前已经算出\(\prod_{i=1}^{M}(1+ix)=\sum a_ix^i\),然后算出\(\prod_{i=1+M}^{2M}(1+ix)=\sum a_ix^i(1+Mx)^{M-i}\)展开之后可以卷。

其实可以组合意义:可以看做一个\(1\)\(n\)的数轴上,一个点在上面跳动,可以不跳,或跳到后面的一个格子并乘上原来所在格子的贡献。要求恰好操作\(m\)次。于是上面的部分就是这个的生成函数,因为可能有时候不跳,所以要乘个组合数,就是下面那个东西。


6084. 【GDOI2019模拟2019.3.25】礼物(口胡)

首先套个polya得到\(\frac{1}{n}\sum f(\frac{n}{d},\frac{m}{d},k)\phi(\frac{n}{d})\)。其中\(f(n,m,k)\)表示长度为\(n\)\(m\)个要求选的连续段长度不超过\(k\),首尾相接连续段长度不超过\(k\)

枚举首尾连续段的长度和\(i\)(如果首尾长度都是\(0\)则为\(0\))。剩下的可以看做有\(n-m-1\)个连续段。生成函数:\((\sum_{i=0}^kx^i)^{n-m-1}\sum_{i=0}^kx^i(i+1)\)。然后随便做。

可以容斥,先\(O(k)\)枚举首尾,然后\(O(\frac{n}{k})\)枚举存在有多少个长度为\(k\)的连续段。相当于有\(n-m-1\)个箱子先给若干个箱子丢一些\(k\)。反正可以组合数算。

还有神仙做法:钦定某个位置选\(0\),然后计算方案数\(f\),再加起来。于是一种特定方案会被算0的个数次。由于钦定哪个位置选0方案数都是一样的,所以得到\(f\frac{n}{n-m}\)。这样就考虑掉了首尾相接。


6083. 【GDOI2019模拟2019.3.25】芬威克树(口胡)

如果当前某个数\(x\),它的最低位的位置可能会变,那大概是要变\(O(\lg k)\)次。那么它在跑的过程中,到死循环为止,只有\(O(\lg^2)\)次,暴力维护之。

至于死循环,可以看做一条链,然后在链的某处打上标记。于是查询链上的某个点相当于求前缀和。

拉出每一条要用到的链并进行一些维护。判断两点是否在同一链上,用数论方法分析考虑计算链首。通过从链首到当前点的进位次数,以及当前点的最低位是什么,可以用倍增倒推回去。


ARC115

A:发现\((-1)^{popcount(x\ xo r \ y)}=(-1)^{popcount(x)}(-1)^{popcount(y)}\),然后算。

B:首先差分,然后决定\(A_1\),算一下使\(A_i,B_i\)非负。

C:\(c_i=i的可重质因子个数\)。显然这是下界。

D:对于一个连通块建出一棵生成树,非树边任意选后,可以通过树边来调整得到每个点的度数的奇偶性,而且调整方式唯一。于是对于一个\(m\)大小的连通块,有\(\sum_{n}\binom{m}{2n}x^{2n}\)的贡献再乘上\(2^{非树边个数}\)。所有连通块的这个东西卷起来就是答案。把这个东西转化成个\(\frac{1}{2}\sum_n\binom{m}{n}x^n+\binom{m}{n}(-x)^n\),稍微推推式子就可以\(O(n^2)\)做了。

E:朴素DP,线段树维护就过了。其实可以把DP中存的值分成几段,这几段对应着从前往后扫过来得到的一个单调栈。在单调栈上面维护点前缀和,打标记之类的,似乎就可以\(O(n)\)了?


Codeforces Round 709(Div1)

A:前四题中最难的题。不考虑限制,先随便分配一下。如果存在一个数出现次数超过限制,那就尝试给它缩到不超过限制。缩完之后再判断一遍即可。因为当众数改变的时候,它们要么相等要么相差不超过\(1\),此时就在限制以下。

B:模拟即可。

C:单调栈+线段树。

D:逆floyed。\(f_{i,k}\leftarrow f_{i,j}-d_{k,j},f_{k,j}\leftarrow f_{i,j}-d_{i,k}\)注意两个都要写不然会锅。


7023. 2021.03.25【2021省赛模拟】排列之美

std做法是先FWT,用点值exp,再IFWT回去。

然而其实可以暴力做,根本跑不满。在数据范围内卡不掉。

其中要算个\(f_S(n)\)表示\(n\)个点形成若干个轮换,每个轮换大小在\(S\)中的方案数。写出方程,稍微做点变化,就可以把最内层循环的模法消去,常数极小。

其实这本身也就是求exp。


7024. 2021.03.25【2021省赛模拟】重生

看到and就想到分段。一共\(K\)位,把后面\(w\)位分出来。询问时枚举前面,查后面;修改时固定前面,改后面。一种做法是把询问分治。时间是\(O(n\lg n2^w+q2^{K-w})\)。虽然看起来\(w\)可以偏一点但实际上\(w=\frac{K}{2}\)最优。只能跑进4s。

wmy的爆标:\(O(n2^{K/2})\)。对于一个询问,对于其最优解,枚举前半段,查询其是否存在(维护每个最后出现位置)得知最优解的前半段是什么,然后固定前半段查后半段是什么。

题解的做法:建Trie,把\(1\)儿子合并到\(0\)儿子上,然后就可以按位确定。由于不方便修改,所以要定期重构。dyp的改进:把Trie换成直接维护高维前缀和。

yyt的爆标:把定期重构换成二进制分组,然后就可以\(O(n\lg^2n)\)啦?

posted @ 2020-12-18 22:26  jz_597  阅读(810)  评论(0编辑  收藏  举报