Loading

21.11 杂题

mark 一些自己最近见的经典题。每题大概都会有听过不同做法。难度还是按 cf 那篇的难度来判。有一些部分还不是很懂先留坑。

P1[4]

https://www.luogu.com.cn/problem/P2161

这题主要有一车不同的做法。

算法1

考虑直接线段树区间染色,然后如果查询的区间有部分到了这某个区间,就把这个区间删掉。复杂度 \(O(n\log^2{n})\) 吧(大概)。

算法2

分块做法更加暴力,每个块搞一个vector存所有经过这个块的区间即可。复杂度 \(O(n\sqrt{n})\)

算法3*

考虑树状数组。还不是很懂。

算法4

还有一个平衡树的思路,或者叫区间树。我们定义 \(<\) 为严格在其左边的,\(>\) 同理,那么所有有交的部分就是相等的部分。这个平衡树使用 stl set维护即可。

P2[4]

A 要确定 \(p_i\),B 要确定 \(q_i\),有一个式子 \(\sum a_ip_i(1-q_i)\),A 要最大化这个式子,B 要最小化这个式子。求最后这个式子的值。\(\sum p_i=1,\sum q_i=1\)\(1\le n\le 30,1\le a_i\le 40\)

根据最小最大值定理,我们发现满足一个人(也就是求min的max)即可满足另一个人。

算法1

二分一个答案 mid。考虑B能否让式子的值 \(\le mid\)。那么只需考虑 \(a_i > mid\)\(i\),然后要满足 \((1-q_i)a_i\le mid\),也就是 \(q_i\ge 1-\frac{mid}{a_i}\)。注意 \(q_i\ge 0\)。然后求和看有没有超过 \(1\) 即可。

算法2

根据二分算法可以得知 \(mid=\frac{n-1}{\sum \frac{1}{a_i}}\) 是临界点。但其实不然,因为老师有可能不去某些教室,然后发现去的教室一定是从大到小排好序的一段前缀(这样可以让分母尽量小)。于是可以 \(O(n+V)\) 做。

算法3

考虑拉格朗日乘数法,可以算出 \(p_i\)\(\frac{1}{a_i}\) 成正比(大概是柯西的条件),然后设比值为 \(k\)。根据 \(\sum p_i=1\) 可以算出 \(k=\frac{1}{\sum \frac{1}{a_i}}\),然后带回原式,发现答案即为 \(\frac{n-1}{\sum \frac{1}{a_i}}\)。剩下的部分同算法2。

P3[4]

https://www.luogu.com.cn/problem/P4643

算法1

这种套路见多了也就觉得不难了。

注意到最后是求两者之差而不是都求出来,那么一定有猫腻。那么考虑每条边的贡献,如果两个端点都在A的集合内贡献是 \(c\),在不同的集合贡献是 \(0\),否则是 \(-c\),那么考虑把这个贡献算到两个点里,分别给两个点加 \(c/2\),容易发现这就对了。然后从大到小排序依次选即可。那么这道题就做完了。

P4[5]

http://noi.ac/contest/596/problem/2530

\([x^m]\prod_{i=1}^{n} \sum_{j\ge 0} (a_ij^3+b_ij^2+c_ij+1)x^j\)\(nm\le 10^7\)

算法1(std)

我们观察一下后面那个生成函数:

\[F(z)=\sum_{i\ge 0}(ai^3+bi^2+ci+1)z^i\\ F(z)=zF(z)+1+\sum_{i\ge 1}(3ai^2-3ai+a+2bi-b+c)z^i\\ F(z)=\frac{1+\sum_{i\ge 1}(3ai^2-3ai+a+2bi-b+c)z^i}{1-z}\\ \]

然后再类似的推一推可以得到:

\[F(z)=\frac{1+(a+b+c-3)z+(4a-2c+3)z^2+(a-b+c-3)z^3}{(1-z)^4} \]

于是上面的部分直接卷积,下面相当于卷上一个 \(\sum_{i\ge 0}x^i\) 四次,也就是做四次前缀和。

算法2

\(f_n=an^3+bn^2+cn+1\)。然后考虑爆求通项,这玩意显然线性递推,于是高消消消乐。但是这个做法挺没前途的eeee。

算法3*

还是推生成函数。这里简记一些生成函数的性质(选自《具体数学》)。

\[幂级数:A(z)=\sum_{k\ge 0}a_kz^k\\ 第 n 项:[z^n]A(z)=a_n\\ 卷积:[z^n]A(z)B(z)=\sum_{i=0}^{n}a_ib_{n-i}\\ A(z)=\sum_{i\ge 0}\binom{r}{i}z^i=(1+z)^r\\ (1+z)^r(1+z)^s=(1+z)^{r+s}=\sum_{i\ge 0}\binom{r+s}{i}z^i\\ [z^n]\sum_{i\ge 0}\binom{r+s}{i}z^i=[z^n](1+z)^r(1+z)^s=\sum_{i=0}^{n}\binom{r}{i}\binom{s}{n-i}\\ \Rightarrow \sum_{i=0}^{n}\binom{r}{i}\binom{s}{n-i}=\binom{r+s}{n}\\ \sum_{i\ge 0}z^i=\frac{1}{1-z}\\ aF(z)+bG(z)=\sum_{n}(af_n+bg_n)z^n\\ z^mF(z)=\sum_{n}f_{n-m}z^n\\ \frac{F(z)-\sum_{n=0}^{m-1}f_nz^{n}}{z^m}=\sum_{n\ge 0}f_{n+m}z^n\\ F(cz)=\sum_{n}c^nf_nz^n\\ F'=\sum_{n}(n+1)f_{n+1}z^n\\ zF'=\sum_{n}nf_{n}z^n\\ \int_{0}^{z}F(t)dt=\sum_{n\ge 1}\frac{1}{n}f_{n-1}z^n\\ \frac{1}{1-z}F=\sum_{n}(\sum_{i=0}^{n}f_i)z^n\\ \]

然后大概知道了这些性质也就可以做题了:

\[F(z)=\sum_{n}n^3z^n= \]

反正也就是用上面的性质,先不管了。

P5[5]

http://www.szoj.net/contest/441/problem/6787

算法1(std)

考虑把最短路图(网)建出来,然后必然是加一段1到n的必经边。然后考虑剩下的边的情况,直接考虑不好考虑,所以二分答案,把所有可行的边(\(dis[1,u]+dis[v,n]+w(u,v)<mid\))加入,再判断修改必经边是否可行即可。

算法2

上述算法不好直接考虑的原因是这是一个图,我们考虑建出最短路树。然后考虑一个经典结论:

  • 如果段一条边,其他非树边产生的贡献(其中一点为 \(n\) 的子树内的点) \(dep_u+dep_v-dep_n+w(u,v)\) 或者 \(dep_u-dep_v+dep_n+w(u,v)\)\(v\)\(n\) 的祖先),且最多经过一条非树边。

然后对于删除 \(n\) 的祖先这条链的边都可以产生贡献,于是就变成了一个区间取 \(max\),只有单点查询直接标记永久花即可。

算法3

好像对于所有这样的边从小到大排序,然后树上并查集合并一条链代表段这一条链的最小值都是当前值。

算法4

算法2的过程还可以直接线段树合并。

P6[8]

http://www.szoj.net/contest/441/problem/6468

转换问题把边看成两个不同的点,然后在同一顶点处匹配两条”边“。于是这等价于 \(K_{2,2,2,...}\) 匹配。

算法0

打表&oeis

算法1

根据 U 群大佬,先容斥得到和式,然后写成卷积形式列生成函数,然后 ODE(成熟方法

可以得到和 oeis 同样的递推式

算法2*

考虑dp,记 \(f_{i,0/1/2}\) 代表前 \(i\) 组还有 \(0/1/2\) 个点没有匹配的方案数。然后转移。

具体还不是很懂,先留个坑(

P7[6]

https://www.luogu.com.cn/problem/P6822

P8[7]

https://www.luogu.com.cn/problem/CF156D

算法1

直接背结论:\(n^{k-2}\prod a_i\)

P9[5]

https://www.luogu.com.cn/problem/CF1149C

线段树 Merge 的经典套路。考虑所有为 \(s[k+1,r]-s[l,k]\),那么就枚举 \(k\)\(mid\) 的哪边。

P10[3]

https://www.luogu.com.cn/problem/P4145

Segment beat 裸题。我们发现如果一个点不会被改多次的话就暴力去改,复杂度 \(O(n\log n\log\log n)\)

P11[5]

https://www.luogu.com.cn/problem/P7888

子序列相关计数的经典题。要求本质不同,那么考虑一个套路:在其第一次出现的地方计数。

那么考虑一个子序列 \(p_1,p_2,...,p_k\),其对应颜色为 \(c[p_1],c[p_2],...,c[p_k]\),那么所有包含其的子序列就得满足条件:

  • \([1,p_1-1]\) 中不能有 \(c[p_1]\) 这种颜色
  • \([p_1+1,p_2]\) 中不能有 \(c[p_2]\) 这种颜色
  • \(\dots\)
  • \([p_k+1,n]\) 中随便选。

那么我们对于一种答案就可以对包含其的子序列计数。但是这样还不是多项式式复杂度

考虑子序列相关的一种dp套路,记 \(f_i\) 代表以第 \(i\) 个数结尾的答案,也就是 \(i=p_k\),那么枚举上一个是啥,设为 \(j\)。有 \(f_i=f_j\cdot 2^{w(j,i,s_i)}\),其中 \(w(i,j,c)\) 代表 \((i,j)\) 中有多少个不是 \(c\) 的元素。复杂度 \(O(n^2)\)。然后考虑优化,这个形式看上去很前缀和,我们只需要维护前缀 \(\times 2\) 即可。但是我们发现这个 \(\times 2\) 和具体的 \(s_i\) 有关,大概可以对面的每个位置 \(j\),维护 \(g_{j,c}=f_j\cdot 2^{w(j,i,c)}\),然后考虑维护这个东西的前缀和,于是对每种颜色维护好像就可以了,复杂度 \(O(\mid\sum\mid n)\) 可以通过。

P12[8]

http://www.szoj.net/contest/429/problem/6453

直接记录 \(lst_i\) 为在其之后最近的同色点出现位置减去它的位置的值。然后判断这个值是否相同即可。然后我们发现是要求后缀的 \(lcp\)。然后发现可以后缀排序比较,直接比较用可持久化平衡树多一个 \(log\),我们可以使用可持久化分块平衡复杂度。

P13[7]

http://www.szoj.net/contest/427/problem/6440

直接树形背包,然后发现转移大概是:

\[(a_ux\prod (F_v(x)+1) \]

于是你发现这就是一个(最多)\(n\) 次多项式。于是考虑插值的套路直接维护点值的上述式子的和。然后这个就很好换根,然后就可以 \(O(n^2)\) 了。

P14[6]

https://www.luogu.com.cn/problem/CF981E

考虑线段树分治,然后bitset优化背包dp即可。

posted @ 2021-11-14 19:44  Semsue  阅读(4)  评论(0编辑  收藏  举报
Title