NOI Online 题解
[NOI Online #1 提高组]序列
首先对两个序列作差,等价于该序列能否变成一个全为 \(0\) 的序列。
对于操作 \(2\) ,连边后等价于一个连通块内和不变,任意加减,所以可以把这个连通块缩点,把和作为权值。
对于操作 \(1\) :
同样先连边。
对于一个连通块内如果不是二分图(有奇环),可以在总和奇偶性不变的情况下任意加减,因为一切不必要的操作可以在奇环中消掉(将奇环理解为自环)。
如果是二分图,每次都是两个不同部分的操作,而操作的差相同,因此可以在两部分差不变的情况下任意加减。
时间复杂度: \(O(N\log N)\) 。
[NOI Online #1 提高组]冒泡排序
首先观察经过一轮冒泡排序排列的变化:
4 3 5 1 2
3 4 2 1 5
可以发现,前面有更大的数(即有逆序对)就会往前一位(前面的数过来)。
也就是说每次操作每个逆序对减少 \(1\) (除了已经是 \(0\) 的)
考虑不带修改操作的怎么做:先把最初的逆序对处理出来,只有那些初始逆序对数大于 \(k\) 的有贡献。贡献为这些的和减掉个数乘以 \(k\) 。用树状数组维护。
接下来考虑有交换操作的,只需要分类讨论对逆序对的贡献即可。
时间复杂度: \(O(N\log N)\) 。
[NOI Online #1 提高组]最小环
首先一个结论:大的数和大的乘,小的数和小的乘。证明考虑交换两个数,一个积没变,一个变小。
接下来考虑如何放置能够满足这个结论:
这些乘积会形成 \(\gcd(k,n)\) 个闭环。
证明:设相隔 \(k\) 个,能放 \(x\) 个,走了 \(y\) 次环,使正整数 \(x,y\) 最小。
则有 \(\frac{n}{x}=\gcd(k,n)\) 个闭环
对于每个环,先放最大的,接着;两边交替放剩下的最大的即可。
而 \(\gcd(x,n)\) 会有 \(\operatorname{d}(N)\) 种取值,因此对 \(N\) 的因数先预处理出来即可
注意特判。
时间复杂度: \(O(N\operatorname{d}(N))\) 。
[NOI Online 2 提高组]涂色游戏
不妨设 \(p_1\ge p_2\) ,随意染色显然选择红色,这个 \(10^{20}\) 可以看做无穷大。
- 先看个奇怪的条件:就是随意染色。
显然选择红色(\(p_1\))因为它左右一定都是蓝色(\(p_2\))
最大的一段连续颜色显然是这样的: \(mp_1<np_2<(n+1)p_2<\cdots<(n+k)p_2<(m+1)p_1\)
当 \(t=np_2-mp_1\ (t>0)\) 最小时, \(k\) 最大。
那么可以得到 \(mp_1+np_2=-t\) 。
根据裴蜀定理,我们知道 \(mp_1+np_2=-t\) 有解当且仅当 \(\gcd(p_1,p_2)|-t\) 。
\(m,n\) 是什么不重要,因为只需要 \(t\) 就能求出 \(k\) 是多少。
显然 \(t=\gcd(p_1,p_2)\) 。
然后就可以求出 \(k=\frac{p_1-t-1}{p_2}\) (下取整)
不过实际的 \(k\) 还要 \(+1\) ,再和题面给出的 \(k\) 比较大小即可。
注意特判。
[NOI Online #2 提高组]子序列问题
注:这个题解的做法比较难看,而且只有一份很丑的代码,之后再修改
考虑维护每次 \(l\) 改变后的答案的变化:
首先看 \(l=1\) 的情况:
如果第 \(i\) 个数前面没有和它相同的,那就对 \(f(l,i)\) 到 \(f(l,N)\) 有贡献。
接下来 \(l=i(i\not=1)\) 时:
考虑 \(l-1\) 没有了贡献,而下一个值和 \(A_{l-1}\) 的就能对后面产生贡献,设此处下标为 \(x\) ,则 \(f(l,l)\) 到 \(f(l,x-1)\) 的贡献都减 \(1\) 。
如何维护这些函数的平方的和呢?同样考虑维护每行的和,再减去差值。
首先维护出每个数的后继并顺便判断前面是否有相同的值。
第一行的和可以第一次迅速求出来。接着若有 \(x\) 个地方值减了 \(1\) ,原来和为 \(s\) 则平方之和减少了 \(2s-x\) 。
用线段树维护和,时间复杂度: \(O(N\log N)\) 。
[NOI Online #2 提高组]游戏
难以求出恰好为 \(K\) 的方案,因为钦定 \(K\) 个后难以保证其它点没有子孙关系。
可以使用二项式反演将至少转化为恰好,只要钦定 \(K\) 个就好了。
接下来考虑如何钦定 \(K\) 个,使用树形 DP :
设 \(F_{x,y}\) 为在 \(x\) 的子树内,钦定了 \(y\) 对子孙关系,可以用背包转移,并额外加上根节点的贡献。
由于是在树上,所以背包时加上树的大小的限制时间复杂度是 \(O(N^2)\) 的。
[NOI Online #3 提高组]水壶
大水题,没啥好写的。
[NOI Online #3 提高组]魔法值
首先这个是否有贡献是和魔法值无关的,只和图长的样子有关。可以考虑计算城市之间互相的贡献,由于是异或运算,只会是 \(0\) 或 \(1\) 。
之后可以用普通的矩阵乘法计算。如用 bitset
优化,理论上是可以过掉这个题的,但不能开 O2 就被卡掉了。
这个多组询问比较奇怪,考虑优化单次询问的复杂度。
如果跟图有关复杂度总是太大了,可以将图给预处理出来,即计算第 \(1,2,2^2,2^3,\cdots,2^{30}\) 天点之间的贡献。
接着用初始魔法值矩阵和这个预处理的矩阵相乘,复杂度是 \(O(N^2)\) 的。正确性等于是过了几天又重新计算。
时间复杂度:预处理 \(O(N^3\log A_i)\) ,询问 \(O(QN^2\log A_i)\) 。
[NOI Online #3 提高组]优秀子序列
看这个欧拉函数加来加去是没有任何性质的,只能先将每种值能凑出来的方案数求出来,再套进欧拉函数求和。
先把 \(0\) 给特判掉, \(0\) 怎么与都是不会有冲突的,最后贡献乘上 \(2^{0\text{的个数}}\) 即可,同样空集也要加上去。
既然是二进制下的运算,先转成二进制考虑,每个数是个至多 \(18\) 个 \(1\) 的集合。
每个数都是由其若干子集组成,可以枚举子集来转移。由于题目中规定是有序的,因此枚举时也要有顺序,考虑从大大小,因为每一位只能由一个数占掉,因此必有一个数大于其它所有数之和,每次用这个数转移。
会有多个一样的数,因此该换成某个值有若干个数,计算方案数时也很方便。时间复杂度: \(N+3^{\log A_i}\) 。
复杂度证明:\(\sum_{i=1}^{N} C_{N}^{i}\times 2^i=\sum_{i=1}^{N} C_{N}^{i}\times 2^i\times1^{N-i}=(2+1)^N=3^N\) 。