2024.2

1. gym103260H Excluded Min

先思考怎么转化原问题,如何 check F(S)x 呢。如果 S<x 的数 x ,显然就合法了;否则的话,我们操作过程肯定会出现一个 x ,而根据题目的过程,出现一个 xx 就不会消失了,所以说相当于是 check F(S)x+1 了。

于是我们找到最大的 t ,使得 S<t 的数 t ,则 F(S)=t

思考怎么计算答案,我们离线下来,把每个询问看成一个二维平面上的点 (l,r) 。从大到小枚举 t ,动态修改这些点对应的 F ,修改相当于是对所有 ax=t ,把 lxr 的部分的 F 减去 1 ,然后再找到所有 Ft 的点,计入答案并删掉。直接做是困难的,因为问题形如对矩阵修改,查最值。

怎么办呢?你注意到一个显然的性质:若一个区间 [l1,r1] 被区间 [l2,r2] 包含,那么 F([l1,r1])F([l2,r2]) 。如果询问区间两两没有包含关系,那问题就是容易的了:这些区间一定是 l,r 同时递增的,于是问题就形如对序列修改,查最值了,容易线段树解决。

回到原问题,我们就尝试只维护这些没有被其它区间所包含的区间,我们称这些区间是好区间。等到一个区间得到答案,被删掉以后,再把新的好区间加进去即可。具体实现时,我们一开始就把所有区间以 l 从小到大排序,若 l 相同再按 r 从大到小排序,我们维护的线段树就都以区间的编号为下标进行维护。维护两棵线段树,一个是当前的好区间对应的 F ,一个是剩下的区间的 r。寻找新的好区间时,我们记删掉的区间编号为 x ,下一个好区间编号为 R ,上一个好区间的右端点是 lim 。利用第二棵线段树,找到 [x,R]r 最大的记为 y ,若 ry>lim ,说明这是一个新的好区间,令 R:=y ,否则结束这个过程。

加入新的好区间时要算它此时的 F ,可以 BIT 解决。总复杂度 O(nlogn)

2. gym103329I Typing Contest

先让 ti 乘上 100 ,令 X=ti ,把权值写成 si(10000ti(Xti)) 。尝试枚举 X ,就变成了经典的 01 背包问题。复杂度大概是 O(5000n3) 的,不能通过。

乍一看是不能优化的,因为权值的计算中 X 是关键的,无法进行有效的变换。于是我们尝试寻找 X 的上界。有结论:X100n+2

原因是,你考虑选取的物品一定有 ti(Xti)<10000 ,否则的话,它本身权值是非正的,还让 X 更大了,删去它是更优的。对这些不等式求和,我们有 X2ti2<10000k ,其中 k 是选取的物品个数。 再对 ti2Xti3<10000ti 求和,我们有 ti2<10000+ti3X10000+(maxti)220000

于是 X2<10000k+ti210000(k+2)10000(n+2)X100n+2

最后复杂度是 O(5000n2) 的。

3. gym102978F Find the LCA

考虑枚举集合 S ,如何计算 lca(n1,n) 的子树内点集为 S 的方案数。先算掉 |S|=n 的情况,之后 n1n 必须在 S 里,1 不能在 S 里。

发现方案数是只和 |S|,minxSx 有关的:子树外的点选取 pi 的方案数就是 (n|S|1)! ,子树内的连边方案数通过找规律发现是 max(2,(|S|1)!)2 。最后子树的根需要往外连边,方案数便是 minxSx1

于是如果没有 minxSx ,直接计算 ([in2]+Aix) 即可,可以分治 NTT 解决;而现在考虑把这个 min 融合进我们的过程:在分治的每个节点维护两个多项式,一个代表上面的连乘式子 Ai,一个是最后想要的式子 Bi ,显然 Ap=AlAr,Bp=BlAr+Br 。复杂度 O(nlog2n)

4. gym102443E Hide-and-Seek for Robots

首先可以观察到,U/DL/R 是不会同时攻击到对方的。所以我们可以分开看 U/D,L/R 的性质,以 U/D 为例。把所有 U 的攻击范围画出来,构成了一个轮廓线把图分成两部分,然后你发现在这个轮廓线上 U/D 皆可,上面只能 U ,下面只能 D 。设轮廓线在第 i 列时的处于的行数为 di ,则 |didi+1|1 。对这个轮廓线做 dp 即可,不合法的 U/D 一定能通过一次旋转变成合法的 L/R 。复杂度 O(n2)

5. gym102341F Flaaffy

首先有一个区间 dp 的思路,就是记 fi,j 表示当前显示的是 i ,结果在 (i,j] 的最小费用,gi,j 同理。但这个 dp 显然是不优的, 注意到需要的费用是很小的,有一个上界是 5logN (N=105) ,实际测试中可以发现费用都在 K=42 以内。 于是我们转而记 li,c 表示最大的 j 使得 fi,jcri,j 同理。

如何转移呢,以 li,c 为例,考虑枚举 check 的点 t ,令 d=dis(i,t)+1 ,我们需要 rt,cdi+1 ,然后用 lt,cd 去更新 li,c。这样直接做是 O(KN2) 的,但我们可以优化。首先注意这里我们不需要保证 t>i ,因为 ti 的时候 lt,d 一定不优。

先枚举 c 。枚举 t 以及 d ,把 (d,t) 这个三元组存进 rt,cd1 这个位置的 vector 中,表示从这个位置开始就能产生贡献。存完了之后就开始从左往右扫,设 qi,S 表示 i 这个数在 S 中的位全变成 0 得到的数。对于扫到的二元组,枚举 S 满足 popcount(S)=d1 ,用 lt,dc 更新 wqt,s,s 即可。再更新当前的 li,c ,就是枚举 S ,用 wqi,S,S 更新即可。复杂度 O(25NK)

6. P10064 [SNOI2024] 公交线路

Si 表示叶子 i 一步到达的点集,则 Si 需要两两有交。不难发现这是充要的。

由于 Si 都是树上的某个联通块,则所有 Si 的交一定非空,且构成了一个联通块。考虑点-边容斥,以点为例,我们要计算所有 Si 都包含一个点 x 的方案数。首先两端都是非叶子的路径,以及不跨过 x 的路径可以任意取,不影响结果。然后考虑进行容斥,钦定一些叶子的 Si 不包含 x ,设第 i 棵子树内共有 si 个叶子,其中有 pi 个可取叶子, 第 i 棵子树外有 ci 个非叶子,则剩下的路径有 pici+ijpipj 个路径是能取的。

用背包来算这个东西,枚举每个子树,有 fx(1)siy(siy)2y(ci+x)fx+y

但直接做是 O(n3) 的,考虑优化。取 1 为根后,若只考虑 x 除了其父亲外的子树进行转移,容易发现是 O(n2) 的。而我们可以不对最后这棵子树做容斥,直接计算答案:fi(2i+c1)s

边也是类似的,其实还要简单一些,相当于只有两个子树。

7. uoj goodbye

A 直接树形 dp 即可。

B 考虑一个 O(n2) 的做法(先当成 n,m,L 同阶) 。看到字典序最大,尝试逐位确定,变成 check 一个终止序列 b 是否合法。如果一个操作 j 涉及的所有位置 ljirj 都满足 xj,ibi /已被覆盖,那就让它做最后一个操作,并覆盖 [lj,rj] 。循环地找下去。最后如果所有位置都有 aibi /已被覆盖,说明 b 是合法的。

发现这个是可以直接优化的。我们确定 bi 时, 首先 i<lj 的操作是不需要管的;我们优先去选 rj<i 的操作,直到不得不选满足 ljirj 的操作。在剩下这些操作中找合法前提下 bi 最大的即可。可以发现 rj<i 部分的操作结果基本不会改变,只可能是加入一些 rj=i1 的区间时产生了连锁反应,类似于 bfs 找到新的能取的操作即可。复杂度线性。

C 思考怎么 check 一个状态是否合法。把偏序关系形成的树画出来。观察 Sci=0 的部分一定满足 pi 单调递增,否则直接调整即可。

思考 ci=1 的部分会带来什么限制。令 qi 是子树中除 i 自身外 pv 的最大值,那么若有一个 cj=0 且在 S 中的 j 满足 qi<pj<pi ,那交换 pi,pj 是更优的。

感觉后面的 dp 就不难了阿。复杂度 O(nlogn)

D 咕一下。

8. 2.9T2

题意就是,每次询问给出 d,k ,令 ci=(ai+d)modm ,求 c 这个串 k 小后缀的位置。

考虑建出 height 数组的广义笛卡尔树。把询问按 d 排序,思考随着 d 变化,我们的 SA 数组如何变化,你发现相当于是在建出的树上把某些点的最后一个儿子换到了第一个。而这个换位操作的总次数是 O(n) 的。每次相当于是把 SA 数组相邻的两段区间进行交换,使用文艺平衡树维护即可。一个问题是每次操作时如何在 SA 中定位,我们维护一个序列 rki 表示一开始 rank=i 的后缀现在的排名是多少,每次操作时 rk 的变化就是两次区间加,于是用线段树维护即可,算出 rk 就能进行定位了。

9. qoj2563 Curly Racetrack

首先注意到,若只是看是否闭合,横向的水管是和竖向独立的。

只是在判断是否为好格子的时候横竖会有联系。一个格子是特殊格子,等同于它两个方向都只接了一条水管。

于是现在以横向的为例,我们会尽量让所有格子都只接一条水管。但有时候是无法实现的。

我们枚举每一行,已出现的水管把这一行划分成若干段,两段之间是独立的。设只往右边连的是状态 1 ,只往左边连的是状态 0 。不确定的为状态 2 ,直接把状态 2 的看做坏格子。那不能出现相邻的 0 /相邻的 1 ,否则就不闭合了。状态 2 是一定合法的,因为它一定能根据左右两边的接法调整成合法的状态。

如果左边的状态为 X ,右边的状态为 Y ,两端的列数之差为 c 。那如果 cXY 的奇偶不同,则说明这一段中间一定有至少一个 2 ,否则直接 0,1 交替的填即可。观察题意给出的三类限制,A类是不能产生贡献的格子,B类是必须当好格子,C类无所谓。一开始我们认为所有 B,C 类格子都是好的。当前段中若有 A 类的话直接让其为状态 2 即可;否则就得选择一个 C 类格子降级为坏格子,让答案减 1。

竖着类似的再做一遍。但是你发现这样会算小答案。原因是有些 C 类格子的贡献被扣了两次,但实际上只用扣一次,要加回来。所以要让扣两次的 C 类格子尽量多,这就是经典的二分图最大匹配,直接计算即可。复杂度 O(nmnm)

10. qoj8240 Card Game

可以把问题转化成:从 l 跳到 r ,若当前 fur 就跳到 fu 否则跳到 u+1

考虑直接用主席树维护答案,从大往小计算,先让 Ti 复制 Tfai 的信息,然后把 Ti+1(i,fai) 这一段加 1 并复制到 Ti 上。

区间加可以用标记永久化实现,于是复杂度 O(nlogn)

可以写的很帅的。

int cop(int l,int r,int z){int u=++cn;ls[u]=l,rs[u]=r,tg[u]=z;return u;}
int ko(int p1,int p2,int l,int r,int x,int y,int z1=1,int z2=0){
    z1+=tg[p1],z2+=tg[p2];
    if(x<=l&&r<=y)return cop(ls[p1],rs[p1],z1);
    if(y<l||x>r)return cop(ls[p2],rs[p2],z2);
    int mid=(l+r)>>1;
    int L=ko(ls[p1],ls[p2],l,mid,x,y,z1,z2),R=ko(rs[p1],rs[p2],mid+1,r,x,y,z1,z2);
    return cop(L,R,0);
}

11. qoj8232 Yet Another Shortest Path Query

神了。考虑平面图的性质:m3n6 。所以度数最小的点度数不超过 5 。我们每次删掉这个度数最小的点,直到把图删空。然后把每条边定向: 若 uv 先删则连 uv

u 走向 v 时,若方向是 uv 则写下 R ,否则写下 L 。你发现从 st ,第一条是 R 的情况可以直接处理掉:枚举 s 的出边,即可转化成只能走两条边的询问。同理,最后一条是 L 又能处理掉。只需要考虑 LLR 和 LRR,而 LLR 看成是从 t 出发就成了 LRR,所以只用考虑 LRR。把询问离线下来,把 s 相同的询问一起处理。枚举 s 的一条入边,再枚举两个 R 的走法,用桶记下来答案,询问就好处理了。这部分复杂度是 O(52m) 的。但我们还需要快速的弄 10q 个两条边的询问。还是同样的处理掉第一个为 R/最后一个为 L,来考虑 LR ,离线即可。

复杂度大概就是 O(52(m+q)) 的。

12. CF786D

一开始的想法是换根的同时直接维护 s(rt,x) 的大小关系,但发现这是困难的。

树上的数点问题,尝试点/边分治,这里边分治要方便一些。对于当前取的这条中心边,我们统计一端的点 z 对另一端的询问 (x,y) 的贡献。你发现这个时候,s(x,z1)s(x,z2) 的大小关系是和 x 无关的:因为 s(x,z) 可以拆成 s(x,t)s(t,z) ,其中 t 是中心边的端点。 s(x,t) 是固定的,所以只和 s(t,z) 有关。 按 s(t,z)z 排序可以直接建 trie 树实现。

排序完之后,处理询问就是直接二分,转化成快速对 s(x,z)s(x,y) 进行比较,利用哈希+二分算 lcp ,由于需要求 k 级祖先,这是单次 O(log2n) 的。总复杂度 O(nlog4n)

(ps:发现可以做到 O(logn) ,树剖即可)

做得有点直接,还有优化空间。对于询问我们先比较 s(x,t)s(x,y) ,如果它们 lcp<|s(x,t)| ,说明大小关系已经固定了;否则, (x,y) 这条路径删掉前 |s(x,t)| 这一段,(也就是 x 往前跳),只要找到它和 trie 树的 lcp,就容易计算答案了。

还是二分,可以 O(logn) 算出路径前 mid 条边的哈希值,然后看这个哈希值是否在 trie 的某个节点存在即可。可以 unordered_map 实现。复杂度 O(nlog3n)

13. P10062 [SNOI2024] 拉丁方

先思考 C=n ,建立二分图,左边代表列,右边代表值,若值 j 没有在列 i 中出现就连边 (i,j) ,跑最小边染色即可,第 i 种颜色代表第 R+i 行。显然此时左右两边的点度数都是 nR ,所以合法。

进一步思考 C<n 。尝试先把右边 R(nC) 的区域填了,从而转化成 C=n 的问题。你发现是类似的,建立二分图,左边代表前 R 行,右边代表值即可。需要用 nC 种颜色给这个二分图边染色,所以若有点度数 >nC 就不合法了。第 i 种颜色代表第 C+i 列。

复杂度 O(Tn3)

14. CF1909I Short Permutation Problem

固定 m ,考虑以 n,n1,n2,,m,m1,1,m2,2, 的顺序插入数,考虑 k=n1 时,我们每次插入时就要求两端都是 m2 的数,那每次可插入的位置个数一定是固定的:遇到 m2 的数则空位 +1 ,否则空位 -1。

现在思考 kn1 怎么做,二项式反演一下,转化成钦定 k 个位置满足限制。也就是最后要形成 nk 个非空的段。就能看成初始有 nk 个空位,一样的算。但这样无法保证非空的,于是再容斥一下,钦定一些段是空的即可。

两步都是卷积的形式,可以优化,复杂度 O(n2logn)

15. 有趣的数学题

考虑这样一个问题:在 d 维空间里从原点出发随机游走,每步从 2d 个点中随机选一个,问走回原点的概率。直觉上总是会走到原点的,但实际上并不是。

有结论:设 pdd 维时走回原点的概率。 d2pd=1 ,否则 pd<1

分析一下为什么,我们利用生成函数来计算:

Pn,ddn 步第一次走回原点的方案数, Qn,ddn 步走回原点的方案数,Pd(z)=n0Pn,dznQd(z) 同理,则 pd=Pd(12d) 。而 Pd(z)=11Qd(z) ,于是转化成求 fd=Qd(12d)fd= 说明 pd=1 ,否则 pd<1

思考怎么算 Q 。有 Q2n,d+1=kn(2n2k)(2(nk)nk)Qk,d

(2nn)q2n,d=Q2n,d ,可以发现 q2n,1=1,q2n,d+1=kn(nk)2q2k,d

现在先来算 f1 。有 f1=n0(2nn)22n 。由于 (2nn)22nn ,所以 n0(2nn)22n1+n112n1+12n11n 。于是 f1=

f2 同理,我们能计算出 q2n,2=(2nn) ,于是 f2=n0(2nn)24n1+14n11n 。则 f2=

d3qn,d 就变得复杂了,无法直接计算。

现在我们假设已经知道这样一个神秘结论:对于 d3q2n,dd2nn

那么我们有 fd=n0(2nn)(2d)2nq2n,d1+n122nn(2d)2nd2nn=1+n11n3/2<

问题转化成证明神秘结论。我们可以归纳证明。对于 d3q2n,d+1=k=0n(nk)2q2k,d1+k=1n(2n2k)d2kk(1+d)2nn

最后一步是因为我们能说明 (2n2k)d2kk1n((2n2k)d2k+(2n2k+1)d2k+1) 。转化成 nk1+2n2kk+1dd3 时这是一定成立的。

所以只需看 d=3 时结论是否成立。就是证明这个式子: k=0n(nk)2(2kk)9nn

考虑左式的组合意义,就是有长度为 2n 的序列,填上 0,1,2 使得前一半中的 0 个数和后一半相同,且 0 个数 = 1 个数。那我们考虑,已经填了前 n 个之后,相当于限制了每种数在后面的出现次数,所以上界是 M=maxm1+m2+m3=n(nm1m2m3) 。而 M3nn+1 ,于是 k=0n(nk)2(2kk)3nM9nn+19nn

16. topcoder18429 DiscountedShortestPaths

首先固定了边集之后,一定是用第 i 大的折扣券去折扣第 i 大的边。

然后有一个神奇的 trick:我们用最小生成树来刻画这种权值特殊的最短路径。用集合 S 形成的最小生成树的权值,来更新 iS,jS 的所有 ansi,j 的答案。容易发现是正确的。复杂度 O(2nn2) ,且空间是 O(n2) 的。

17. ucup2-23C Equal Sums

一帮子强队没做起的诈骗题。考虑设 fa,b,c 表示 i=1axii=1byi=c 的方案数,fa,b,0 即为答案。直接转移是 O(n3V) 的,但你发现 fa,b 既能由 fa1,b 算得也能用 fa,b1 算得。那如果 c>0 ,我们就用 fa1,b,d 算,否则用 fa,b1,d 算,你发现如果 |c|V ,那也满足需要的 |d|V 。这样就是 O(n2V) 的了。

18. LOJ3655. 「2021 集训队互测」染色

有技术的 ds 。首先每一列的白色格子连续段可以用 set 维护。每次操作我们会删除某一列的一些连续段,加入一些连续段。把这些连续段拆到线段树的节点上,就是对每一个节点维护一个可删堆,表示最小的列数。每一行此时的权值就是它代表的叶子到根所有节点的权值 min。剩下的任务就是维护标记表示对区间最小值的权值进行修改。注意如果该节点的最小值就是由它自身的堆贡献,那就变成全局修改了。这样就做完了,复杂度 O(nlog2n)

19. ucup 1-1 J Referee Without Red

很酷。首先把这个操作当成是对行/列做了一个置换。我们根据对行操作时的置换,把在一个环内的列换到一起,列同理。那么此时元素的交换就有一个初步的轮廓:相当于拆成了 AB 个子矩阵,元素只在每个子矩阵内相通。

每次操作就是对某一行的子矩阵的相同的行做了一个循环位移的操作,列同理。如果对于一行子矩阵,这些子矩阵的行数是 1 ,那列操作就影响不到这一行了,变成序列的问题,求每个子矩阵的周期的 lcm 即可。列同理。

现在每个矩阵长宽都 >1 。我们尝试设计元操作,使得一个子矩阵在不改变其它子矩阵的情况下实现自身的变换。发现是可以的,只是不能改变奇偶性,奇偶性可以定义为:这个子矩阵元素从上往下,从左往右看的逆序对个数。

那如果这个子矩阵元素不是互异的,说明任意状态都能到达,不用管了;否则,先把答案乘上 |S|!2 , 现在就能把这个子矩阵看成 0/1,看最后能形成多少不同的 01 矩阵。每次行操作等同于:对于这一行子矩阵,列数是偶数的全都进行异或。

建立一个左边 A 个点,右边 B 个点,中间一个 0 的图。每个子矩阵就可以转化成一条边,权值为两个端点的异或值,求最后有多少套不同的边权。答案就是 2

20. gym104008I Invincible Hotwheels

建出所有串的 AC 自动机。考虑枚举最长串 S。对于 S 的每个前缀找到对应的节点在 fail 树往上跳遇到的前两个终止点。这个可以先预处理出来。我们称之为最长/次长后缀。然后考虑一个串是最短串的条件。首先它在 S 中每个出现的位置都得是该前缀的最长/次长后缀,否则可能的中间串至少两种,不合法。把每个次长后缀的父亲到根的点都染黑,如果一个串对应的节点被染黑了就不合法了。这可以拍成 dfn 序后用 BIT 维护。

然后考虑找中间串。我们只需考虑最长/次长后缀,因为如果更短的也能作为中间串,那最长/次长后缀也能,可能的中间串就有三种了,矛盾。现在对这些最长/次长后缀做二维偏序即可,对于一个可能的最短串,看包含它的中间串是否编号全部相同即可。令 L=|S|,复杂度就是 O(LlogL)

21. gym104065B Call Me Call Me

一个直接的做法是 KDT,但这太丑陋了。考虑 KDT 的复杂度是 O(nn) ,我们尝试设计其他根号算法。

首先有一个直接的暴力做法,就是把每个区间插到线段树的 O(logn) 个节点上,每次删除掉 x 的时候,考虑包含 x 的所有节点,把放在该节点上的区间的权值全部进行更新。

尝试设立阈值 B ,让每个区间还需要的权值 B 时才插入线段树中。一个区间一满足条件就插入是难以做到的,但只要让插入时权值还 >0 就好了。考虑删 B 个数只会让权值减少至多 B ,我们只需每次在删掉的数个数恰好为 B 的倍数时尝试加入,因为本来权值 >B 的区间此时权值一定还 >0

每个区间的权值只会进行至多 B 次更新,被尝试加入至多 nB 次,所以复杂度 O(n(B+nB)) ,平衡一下就是 O(nn) 的了。

posted @   grass8woc  阅读(529)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示