2021年7月做题记录

[JSOI2009]球队收益(紫)

(https://www.luogu.com.cn/problem/P4307)

标签

网络流,差分

思路

又有胜利又有失利,很麻烦,所以考虑先让所有人除了一开始的 aa 场外全部失利,再用费用流跑出胜利的费用。

初步思路,对于一场比赛,从源点向它连容量为 11 价值为 00 的边, 从它向两个球队各连容量为 11 价值为 00 的边,表示每场比赛可以选择一只球队获胜,然后从每个球队向汇点连容量为 mm 费用为多获胜一场后奖金的变化量的边

然后求一下变化量,设已经获胜 aa 场, 失败 bb 场.

[C(a+1)2+D(b1)2][C(a)2+D(b)2]=[Ca2+C+2Ca+Db2+D2Db][Ca2+Db2]=C+2Ca+D2Db[C(a + 1)^2 + D(b - 1)^2] - [C(a)^2 + D(b)^2]\\ = [Ca^2 + C + 2Ca + Db^2 + D - 2Db] - [Ca^2 + Db^2]\\ = C + 2Ca+ D - 2Db\\

失败场次等于总场次减获胜场次,总场次是 ai+m+bia_i + m + b_i 设为 kk,所以 b=kab = k - a

所以

C+2Ca+D2Db=C+2Ca+D2D(ka)=C+2Ca+D2Dk+2Da=C+D2Dk+2(C+D)aC + 2Ca+ D - 2Db\\ =C + 2Ca + D - 2D(k - a)\\ =C + 2Ca + D - 2Dk + 2Da\\ = C + D - 2Dk + 2(C + D)a

变化量不是定值,而是一次函数,但因为 C+D>0C + D > 0, 所以这个一次函数是单调增的, 所以对于每个变化量建一条容量为 11 费用为变化量的边即可。

Code

[WC2007]剪刀石头布(黑)

(https://www.luogu.com.cn/problem/P4249)

标签

网络流,差分,二项式系数,容斥

思路

简化题面:给出一张竞赛图,有一些边已经被定向,一些边未被定向,问如何给未被定向的边定向,使得图中三元环个数最多。

从图中任选三个点,这三个点构成环当且仅当在选出的图中三个点入度出度均为 11.

令三个点同时满足条件很难,考虑正难则反,先求出三元组总数,再减去无法构成三元环的情况数。对于一个点,如果入度为 kk 那么这 kk 个入点中任选两个点和这个点都不构成三元环,方案数即 (k2)\tbinom{k}{2},因为这是张竞赛图,所以可以不重不漏. 考虑这个点,这个点的一个入点,这个点的一个出点,显然构成三元环。考虑这个点和这个点的两个出点,由于这是竞赛图,所以出点之间也有边,那么在这两个出点中一定有且仅有一个出点有两条入边。所以这种情况会在计算其它点时被计算。

类似于上一道题,考虑增加一个点入度的贡献,发现 (a+12)(a2)=(a1)=a\tbinom{a+1}{2}-\tbinom{a}{2} = \tbinom{a}{1} = a , 贡献递增,用和上一题一样的方法就行.

Code

[NOI2008]志愿者招募(紫)

(https://www.luogu.com.cn/problem/P3980)

标签

网络流

思路

ii 天至少需要 aia_i 个人可以用上下界网络流来满足,从 iii+1i + 1 连一条上界为正无穷,下界为 aia_i 的边。

想办法表示出招募志愿者,志愿者从 sis_i 工作到 tit_i。 所以可以从 ti+1t_i + 1sis_i 连一条下界为 00,上界为正无穷的边,费用为 cic_i,这条边刚好可以为 sis_itit_i 提供流量。

跑无源汇上下界最小费用可行流即可.

Code

[S2oj493]

(https://sjzezoj.com/problem/493)

标签

dpdp + 二分

思路

想一个简单的情况, a=ba = b, 这时候这道题就是一道很水的 dpdp , 设 fif_i 表示以 ii 为根的子树最少要几个回合,贪心的想,显然要先解决 fif_i 更大的子树,再解决 fif_i 更小的子树,于是按照 fif_i 从大到小给子树排个序,fi=fj+jf_i = f_j + j. 复杂度 O(nlgn)O(n\lg n)

然后思考 aba \neq b, 以 aa 为根, 显然对于 bb , 优先占领自己的子树一定是最优的,因为 aa 占领 bb 的子树前要先到达 bb,一定没有 bb 占领快。然后 bb 可以考虑向子树外占领,显然的是它占领的一定是以它的祖先为根的一整棵子树,证明同上。

算出 bb 占领所用的时间,和抛去 bb 占领的子树后,aa 占领其它部分所用的时间。取最大值即为所求。

于是考虑到 bb 占领到的子树一定是以它的祖先为根的一整棵子树,随着祖先深度的减小,bb 占领所用的时间会变长,aa 占领所用的时间会变短,取两者最大值,那么两者的最大值是一个非严格凸函数。可以通过二分求出第一个 fb>faf_b > f_a 的点,再和它左侧最近的点(最后一个 fbfaf_b \leq f_a 的点)取最值。注意因为不是严格凸函数,所有不能三分.

复杂度 O(nlg2n)O(n\lg^2n) 桶排可以优化到 O(nlgn)O(n\lg n) 但是因为二分和排序的常数小,所以没有问题。

Code(https://sjzezoj.com/submission/14644)

[S2oj496]

(https://sjzezoj.com/problem/493)

标签:

dpdp + 计数 + 矩阵

思路

简化题面:多次询问,求区间本质不同子序列个数

考虑对于每次询问暴力,即单次求本质不同子序列个数。

f[i][j]f[i][j] 表示 dpdp 到第 ii 个字符,以字符 jj 结尾的本质不同子序列个数。f[i][0]f[i][0] 表示空串

c[j]c[j] 表示第 ii 个字符。

对于 jc[i]j \neq c[i] f[i][j]=f[i1][j]f[i][j] = f[i - 1][j]

对于 j=c[i]j = c[i] f[i][j]=k=026f[i1][k]f[i][j] = \sum_{k=0}^{26} f[i - 1][k]

复杂度 O(nq26)O(nq26)

考虑优化到多次询问,根据经验需要前缀和求。把转移改成矩阵. 发现矩阵长这样.

100100101000110000100001110010\\ 01010\\ 00110\\ 00010\\ 00011\\

意会一下吧,26×2626 \times 26 挺难画。

设第 ii 个字符的转移矩阵为 AiA_i .

那么区间本质不同子序列个数就是.

(100000)Al...Ar(111111)τ(111111)Arτ...Alτ(100000)τ(111111)Arτ...A1τA1τ...Al1τ(100000)τ(100000) * A_l ...A_r * (111111)^{\tau}\\ (111111)A_r^{\tau} ... A_l^{\tau} * (100000)^{\tau}\\ (111111)A_r^{\tau} ... A_1^{\tau} * A_1^{\tau'} ... A_{l - 1}^{\tau'} * (100000)^{\tau}\\

AτA^{\tau}AτA^{\tau'} 分别如下.

100000100000100111110000110000\\ 01000\\ 00100\\ 11111\\ 00001\\

100000100000100111110000110000\\ 01000\\ 00100\\ -1-1-11-1\\ 00001\\

先计算 (111111)Arτ...A1τA1τ(111111)A_r^{\tau} ... A_1^{\tau} * A_1^{\tau'} 。我们只关注每一列的和.

设当前位置的字符为 cic_i, 第 ii 列的和为 sis_i. Ci,jC_{i,j} 表示矩阵 ii 行, jj 列.

那么 sj=2sjCci,j,s_j^{'} = 2s_j - C_{c_i,j}, Cci,j=sjC_{c_i,j}^{'} = s_j

再计算 A1τ...Al1τ(100000)τA_1^{\tau'} ... A_{l - 1}^{\tau'} * (100000)^{\tau} , 我们只关注第一列的每一项。

发现减法操作对于除了第 cic_i 列外每一列是一样的。都会减去第 cic_i

所以记录一下修改标记,第 cic_i 列单独修改。要用到某一列时减去修改标记,用完后记得加上.

Code

[NOI2019]弹跳 (黑)

(https://www.luogu.com.cn/problem/P5471)

标签

最短路 + 线段树 + 数据结构优化建图。

思路

先考虑 n100n \leq 100 ,我不会做,因为 FloydFloyd 复杂度直接爆炸.

考虑 h=1h = 1 , 即点向区间连边,可以直接线段树优化建图跑最短路。

那么在二维平面上怎么搞,可以使用 KDtreeKD-tree ,也可以用二维线段树。这里使用二维线段树。

但是线段树套动态开点线段树空间复杂度 O(nlg2n)O(n\lg ^2 n ) 过不去. 考虑优化空间复杂度.

内层不一定要套动态开点线段树,可以套 setset

边不一定要真的建出来,直接取出时间最小的矩形,通过线段树求出它包含那些点,记录这些点的最短路长度,并把这些点拓展(把这些能跳到的矩形放到堆中),并在 setset 中删除这些点(因为这些点不会在被用来修改或被其它点修改)。每个点会被删除和用来拓展一次. 时间复杂度(nlg2n)(n \lg^2 n) ,空间复杂度 (nlgn+m)(n \lg n + m)

Code

CF487E Tourists (3200)

(http://codeforces.com/contest/487/problem/E)

标签

树剖 + 园方树

思路

考虑如果这是一棵树,那显然是树剖裸题。但这些操作在一张图上,考虑转化成树上问题。

用园方树,因为对于一个点双,点双内的两个点一定可以通过至少两种方式互相到达,因为如果只有一种方式,那么割掉必经点,图不联通。所有任意一个点,可以在经过最小点后到达其它任意一个点。

对于一个方点,它的值为相邻圆点的值的最小值,圆点为本身的值。

但这样在修改一个圆点时最多有 O(n)O(n) 个方点被修改,复杂度不对。

所以让一个方点的值为子节点的最小值,这样修改一个点时只用更新父节点。

但这样父亲节点就不能贡献给方点了,所以处理询问时对于每个方点要算一下父亲节点,其实只用处理 lcalca 处方点的父亲.

Code

[SHOI2016]黑暗前的幻想乡(紫)

(https://www.luogu.com.cn/problem/P4336)

标签

矩阵树定理 + 容斥

思路

如果没有每个公司至少修一条路的限制,那么就只需要对于每条边设边权为可以修建它的公司数。跑矩阵树定理求生成树边权积的和。

但是这里规定每个公司必须都有路修。可以用容斥,算出至少有 kk 个公司没有修路的情况 fkf_kans=i=0n(1)ifians = \sum_{i=0}^{n}(-1)^if_i

Code

[CQOI2011]放棋子(紫)

(https://www.luogu.com.cn/problem/P3158)

标签

dpdp + 二项式系数 + 计数 + 容斥

思路

设颜色为 ii 的棋子有 did_i

先考虑一维的情况,答案显然是 (nd1,d2,d3...dc)\tbinom{n}{d_1, d_2,d_3...d_c}.

把它拓展到二维上. 枚举当前在放颜色为 kk 的棋子, 已经占了 iijj 列. 设 f[k][i][j]f[k][i][j] 表示放了 kk 个棋子,g[k][i][j]g[k][i][j] 表示用 kk 个棋子占 iijj 列的方案数, 有 : f[k][i][j]=l=0i1r=0j1f[k1][l][r]×(nlil)×(mrjr)×g[dk][il][jr]f[k][i][j] = \sum_{l=0}^{i - 1}\sum_{r = 0} ^{j-1} f[k-1][l][r] \times \tbinom{n - l}{i - l} \times \tbinom{m-r}{j-r} \times g[d_k][i-l][j-r]

还有一个难题,那就是求出 gg.

用容斥 g[k][i][j] = \tbinom{ij}{k} - \sum_{l = 0}^{i} \sum_{r=0}^{j}g[k][i][j](l\neq i \or r \neq j 且 ij \geq k)

最后 ans=i=1nj=1mf[c][i][j]ans = \sum_{i=1}^{n}\sum_{j=1}^{m}f[c][i][j]

Code

[POI2006]PAL-Palindromes(紫)

(https://www.luogu.com.cn/problem/P3449)

标签

思维 + 性质 + 哈希 + 字符串

思路

很棒的一道性质题,最后我还是看了题解.

收集一下条件 :

  1. 每个串都是回文串
  2. 把两个串拼起来
  3. 求拼起来是回文串的方案数

每个串都是回文串一定是一个非常重要的性质。可以通过这一点证出下面的性质:

当且仅当两个回文串的最小循环节相同时,它们拼成的串是回文串

证明如下:

显然回文串的循环节一定是回文串。

先证明必要性, 如果两个串的最小循环节不相同,设两个串的最小循环节分别为 uuvv ,那么拼成的串一定存在一对前缀和后缀满足最小循环节不同。所以拼成的一定不是回文串。

证明充要性,如果两个串的最小循环节相同。如果拼成的串最小循环节个数为偶数,显然是回文的。否则的话,因为中间的串是回文串,两边的串又一一对应。所有拼出的是回文串

证毕。

有了这个性质,这道题就很好解决了,求出每个串的最小循环节,寻找有多少个串的最小循环节和它一样。可以用字符串哈希处理。

Code