JOISC 2016
loj 上有几乎全部的题目,写了题意的就是 loj 上没有的。
D1T1
一开始把题目看错了,还写了棵线段树。
把询问离线,倒着扫一遍,就变成了求最长不上升子序列,用树状数组维护即可。
D1T2
来自 Kubic 的神仙做法。
考虑 Filp 一个位置和剩下所有位置,记录每个数作为答案出现的次数,如果是 1 次,那么这个位置的答案就是这个数,否则对于所有出现次数为 2 的数,就是比这个数更好记的数,我们就可以确定这些数。
发现上述过程可以看做是排序的过程,把小于的数去掉,然后在大于的数里面继续排序。但是我们不知道这个数是什么,于是考虑随机化,每次随机一个我们要 Filp 的位置,这样做的期望次数是 \(O(n)\) 的,可以通过。
D1T3
很厉害的计数题。
先判断无解情况。如果 4 个角是空的或者第 1、3 行有连续 2 个空格就无解。这样第 1、3 行的空格就可以随意填了,相互之间没有影响。
从部分分入手。对于 subtask2,我们把空格形成的连通块拿出来,注意如果一个格子上下都有格子,那么也是可以随便填的,不能在连通块中,又根据无解的条件,可以发现现在最大的连通块大小也只有 5,可以直接暴搜,最后把所有连通块的答案拼起来。
我们还是从连通块入手。我们对第二行连续的空格求答案,然后组合起来。
设 \(f[i][j][0/1]\) 表示第 \(i\) 列,且中间格在前 \(i\) 列的空格中第 \(j\) 个放置,0/1 表示是在上下格子放好后再放还是左右格子放好后再放。记 \(t\) 为第 \(i\) 列第 1、3 行的空格数,转移分 3 种:
- 第 \(i-1\) 列和第 \(i\) 列都是上下放置,转移就是 \(f[i][j][0]\leftarrow t!\binom{j-1}{t}\sum f[i-1][k][0]\)
- 第 \(i-1\) 列左右放置,那么 \(i-1\) 要在 \(i\) 后面,有 \(f[i][j][0]\leftarrow t!\binom{j-1}{t}\sum\limits_{k\ge j-t}f[i-1][k][1]\)
- 第 \(i\) 列左右放置,那么 \(i\) 要在 \(i-1\) 后面,且 \(t>0\),我们枚举第 \(i\) 列的 \(t\) 个空格有 \(c\) 个是在 \(i\) 之前放置,记之前的空格数是 \(tot\),\(g[i][j]\) 表示 \(i\) 个棋子插入 \(j\) 个已放置的棋子中的方案数,有 \(f[i][j+c][1]\leftarrow g[t][j-1]t!\binom{t}{c}\binom{cnt-j+1+t-c}{t-c}\sum\limits_{k<j}f[i-1][k][0]\)
复杂度 \(O(n^2)\)。
D2T1
简单题。
假设我们把 \(i\right i+1\) 当做一条边,那么这是一棵树,我们要求的就是满足条件的点集的连通块数,那么就是点数 - 边数,点数好维护,边数就是 \(\min(a_i,a_{i+1})\ge x\) 的数量,也可以简单用树状数组维护。
D2T2
很厉害的记搜题。
对于一个正方形,我们肯定是在能吃掉其中一块时紧接着吃另一块,那么对于先吃的一块,假设在左边,那么我们就需要先吃左边的三角形的左边一块,其他方向同理,那么我们就可以枚举每个点然后记忆化搜索,如果有环说明吃不了,这样就得到了 \(O(n^4)\) 的做法。
考虑优化。显然可以发现,我们的搜索有大量重复的状态。比如,如果右边的一块需要先吃左边的一块,那么我们搜右边一块时可以在左边一块的基础上搜。那么我们对于每一行,从左往右搜索,后一个继承前一个的状态就可以了。复杂度 \(O(n^3)\)。
D2T3
挺好一题,但是把题目看错了。
首先找合法的充要条件。比如从后往前看,如果最后两个人都是男生,那么显然是不行的;我们一直推下去,就可以得出,如果把男生当做 1,女生当做 -1,那么条件就是后缀和不大于 1。
然后考虑我们怎么重排最优。我们的目的就是让男生尽量靠前,女生尽量靠后,那么可以每次把最后面的一个不合法的男生移动到开头,这样会让中间所有女生的代价加 1,会让后缀和加 1,那么我们需要 \(maxsuf-1\) 次,于是最终代价就是 \(maxsuf-1\)。
D3T1
很新奇的交互题。
先明确我们的目的。我们要求出两两点对之间的距离,那么就必须求出每条边对应重标号意义下哪两个点。
首先容易用 \(4m\) 次来找出 dfs 树,对图重标号和求出每条非树边指向的两个点深度大小关系,然后只保留指向祖先的边。现在的问题就是我们怎么通过给每个点标上 1/2/3 来求出每条边对应的点。
因为只有 1/2/3,我们尝试进行三进制分组。具体地,我们依次枚举当前在确定哪一位,然后进行一遍深搜,每个点的标号就是三进制下当前位的值,那么对于一条返祖边,我们就可以求出它指向的点在当前位是多少,最终把这个三进制数转成十进制就是答案。
移动次数是 \(4m+\left\lceil\log_3n\right\rceil2m=14m\) 次。
D3T2
JOISC 竟然也会出神仙分块题。
先考虑 \(l=1,r=n\) 的部分分。假如我们只进行一次操作,那么我们最后得到的 A 一定是 A 和序列最大值中较大的那个,如果 A 比序列的最大值要小那么 A 会加入序列中,最大值会出来。如果进行多次操作,我们发现在这个情况下我们并不需要知道序列最终是什么样,我们只用知道这个序列中元素组成的可重集,就可以求出每次操作后 A 会是什么,于是我们用堆来维护即可。
然后考虑拓展到一般的情况。我们此时的目的肯定是想办法尽量只关注序列的可重集,而题目的数据范围不大,时限却很大,不难想到分块。
我们将序列分块,每一块维护元素的可重集和每次会将对整个块进行操作的 A 有哪些。对于每次操作,整块可以直接把 A 加入可重集,然后把最大值弹出,这就是操作完的 A。
重点是散块如何处理。我们顺次考虑每个数,然后顺次考虑 A,如果当前的 \(a_i>A\),这样 \(a_i\) 会变成 A,A 会变成 \(a_i\),然后会继续找到下一个比 \(a_i\) 小的 A,继续进行下去。不难发现,\(a_i\) 最终会变成 A 中最小值和 \(a_i\) 中较小的那个,如果 \(a_i\) 比 A 中最小的数还大就会和这个数交换。
设块长为 B,那么我们一次修改整块的复杂度是 \(O(\dfrac{n}{B}\log n)\),散块的复杂度是 \(O(B\log n)\),于是总复杂度就是 \(O(Q\sqrt{n}\log n+n\log n)\)。
D3T3
简单题,但是思路总是对不上。
发现考虑连边不好处理,但是考虑删边就更方便一些。如果一个点的入度大于 1,那么就需要删到只剩一条入边,我们肯定是贪心地保留最大的入边。
问题是可能会有环,那么我们就需要断掉一条环边,选择一条最大的非环边,那么就求出每个点最大的入边和不在环上的最大入边,取差最小的一个就行了。
复杂度 \(O(n)\)。
D4T1
图论题。
容易想到从一个地方开始停留到相邻的地方只需要两步,到冰块旁的地方停留只需要一步。现在有个问题,如果我们有可能重复利用之前放的冰块,那么我们就不好直接计算最小代价了,那么会不会有这种情况呢?
答案是不会的。因为我们从一个位置到一个我们停留过的位置再移动显然是没有直接从这个位置开始更优。
那么我们就可以直接建边跑最短路了。
D4T2
题意:通信题。
Anya 和 Boris 有一棵有根树,每一天 Anya 会标记一些边,她可以给 Boris 发送一个不超过 1000 位的二进制串,Boris 要多次回答一个点到根的路径上有多少条边被标记过,他不知道这个二进制串,但是每次回答可以查看这个二进制串的 20 位。要求你给出两人的策略。
思路:很有意思的通信题,可能是受到了树分块的启发?
首先,Anya 要传递的肯定是每个点到根有多少条被标记的边,而直接传需要 \(n\log n\) 位,这是不能接受的。
因为是在一棵树上,我们尝试尽量多的继承祖先的信息来用更少的位来实现。这里体现了一点点树分块的思想,即标记一些关键点,然后把一个点到根的路径拆成这个点到最近的关键点和从关键点到根两部分。
具体地,我们把所有点按深度模 10 的余数分类,然后取其中数量最少的一类,把这些点标记为关键点。对于关键点,最多只有 50 个,我们记录这些点到根的路径上被标记的边的数量在二进制下的每一位,需要 9 位;对于非关键点,我们只记录这个点的父亲边是否被标记,需要 1 位。因此这一部分我们最多需要用 900 位。
对于 Boris,我们先从当前点往上跳,直到遇到一个关键点,这最多需要 9 次,然后我们查询这个关键点的信息,最多需要 9 次,于是我们就只需要最多询问 18 次来求出答案。
一个小坑点:题目中保证了对于每条边有 \(u_i<v_i\),但是这并不代表 \(fa_i<i\),这个条件其实没用。
D4T3
到了贪心策略,而且是对的,只不过有线性做法,但是看不懂。
因为是要让改动尽量少,那么就是要让匹配的数量尽可能多,那么就直接找到能匹配的范围内有没有同国家的,有就直接匹配,否则就需要修改。复杂度 \(O(n\log n)\)。
标签:那么,log,记录,题解,复杂度,JOISC,提交,2016,我们 From: https://www.cnblogs.com/Xttttr/p/18013724