JOISC2020 题解

LOJ3271「JOISC 2020 Day1」建筑装饰 4

有一个显然的 \(O(n^2)\) 做法,然后用归纳法可以证明任意时刻合法的位置都是一个线段,就可以 \(O(n)\) 了。

要不是这题我才不会想到优化呢

LOJ3272「JOISC 2020 Day1」汉堡肉

考虑 \(\min R,\max L,\min U,\max D\) 这四个值。

如果 \(\min R\ge \max L\)\(\min U \ge \max D\) 那么显然可以退化到一维的情况。

否则,在 \(K \le 3\) 的时候,容易发现边界的四个交点上至少有一个竹签,否则无法把所有边界覆盖,所以可以枚举插了哪个交点,删掉覆盖这个交点的矩形,然后递归。复杂度 \(O(4^Kn)\)

如果这样搜索不出解,那么就只能是四个竹签分别在四条边界上,相当于是有四个变量。

对于一个矩形,如果和三个边界有交,即完整地包含了一条边界,那么显然不需要考虑。

如果只和一个边界有交,那么就是限制了某一个变量取值在某一个区间内。

如果和两个边界有交,那么就是限制 \(x_1\in [l1,r1]\ or\ x_2\in [l2,r2]\)

不妨设一个 01 变量表示是否有 \(x_1\in[l,r]\) ,那么这些限制就可以写成 2-sat 的模型。

由于满足的限制需要有解,所以如果 \([l1,r1]\cap [l2,r2]=\varnothing\) ,那么它们不能同时成立。容易发现,只要满足这些条件,线段的交就一定有解。

于是前缀和优化建边即可。

LOJ3273「JOISC 2020 Day1」扫除

先考虑没有插入的时候怎么做。

对于被推过的灰尘,它们都会在一个形为折线的边界上。

对于折线上的灰尘,满足每次被操作的灰尘一定是一个区间,所以用平衡树上二分即可找到座标被区间赋值的一段。

而对于之前不在折线上的灰尘,可以提前算出它们在哪一次操作之后会被并入折线。

所以没有插入的情况可以 \(O(q\log q)\) 解决。考虑如何处理插入。

对于一个询问,相当于是问一个点经过一段区间的操作之后会到哪里。

用线段树拆成 \(O(q\log q)\) 个这样的询问,放在若干个区间上。

那么此时对于线段树上的一个区间,点集是固定的,就可以按照没有插入的做法做了。

总点集是 \(O(q\log q)\) 的,而总操作次数也是 \(O(q\log q)\) 的,所以复杂度 \(O(q\log^2 q)\)

还有另外一种做法,感觉更好想一些?

这个等腰直角三角形看着比较不爽,所以用类似线段树的拆分方法拆成 \(O(n\log n)\) 个矩形。虽然 \(n\) 很大但是子树内没有灰尘的矩形显然没有必要建出来。

那么可以发现,对于一次修改,只会影响到 \(O(\log n)\) 个矩形。

而修改对矩形内部造成的影响就是比较简单的了:座标取 \(\max\) ,或是把某一个范围内的点全部踢到子树内。可以用各种神奇数据结构维护。

因为深度是 \(O(\log n)\) 的,所以要踢出去的时候可以暴力一个一个处理。

LOJ3274「JOISC 2020 Day2」变色龙之恋

update:写完才发现 \(C_{L_x}\ne C_x\) ,我人傻了……

请自觉忽略关于初始 \(deg=2\) 的所有讨论。

考虑暴力枚举两个点,看它们在一起有几种颜色。如果只有一种颜色那么连一条边。

那么最后一个点连出去的边会有三种:它喜欢的、喜欢它的、颜色相同的。(记为 1,2,3 类边)

显然 cp 关系会形成环,设一个点连向它喜欢的点的边是它的出边。

先假设所有点的度数都是 3 。

那么就可以对于每一个点,枚举两个相邻的点和自己一起询问,只有一种颜色当且仅当另外两个点分别是喜欢它的和颜色相同的。由此可以确定它的出边。

于是可以把所有环边确定,就能确定颜色相同的点对。

然后考虑各种特殊情况。

  • 1,2 不同,3 与 1,2 中的某一个相同,度数为 2 。
  • 1,2 相同,3 与 1,2 不同,度数为 1 。
  • 1,2,3 均相同,度数为 1 。

可以发现对于度数为 1 的点,它的 cp 也是度数为 1 ,并且它的同色点已经确定了。那么可以把这些点和它们连出去的边删掉。

此时一共只有三类点:

  • 1,2,3 都不同且都存在,度数为 3 。
  • 1,2 不同,3 被删掉了,度数为 2 。
  • 1,2 不同,3 与 1,2 中的某一个相同,度数为 2 。

并且我们可以知道每一个点是哪一种。

对于一二类点,它的(环上的)出边在一开始就已经确定了,且出边显然不是重边。

那么从一个出边确定的点开始沿着出边走,就可以得到一整个环的信息。

那么此时只有一种点的信息没有确定了:一整个环都是三类点,环边和重边交替。

此时选连续的三个点 \(x,y,z\) ,若询问结果为 1 则 \(y,z\) 同色,否则 \(x,y\) 同色。

那么就可以把所有关系都得出来了,就做完了。

然而这个图还没能建出来……

注意到这个图是二分图,所以必定可以把所有点分成两个独立集,独立集中的点要么互不影响,要么是 \(L_{L_x}=x\) 的 cp ,但是后一种情况其实也是互不影响的。

那么依次加点,求这个点的所有边,显然可以在两个独立集内分别二分找边。

于是询问次数 \(O(n\log n)\)

LOJ3275「JOISC 2020 Day2」有趣的 Joitter 交友

前面的分析不是很难,但是感觉不是很会实现 /px

对于一个集合,维护 \(point\) 表示集合内的点的编号,\(ine\) 表示连入的点的编号, \(inp\) 表示连入的集合编号, \(outp\) 表示连出的集合编号。

合并的时候,先减掉分别的贡献,合并完成后再加上一整个的贡献。贡献为 \(f(S)=|S|\times (|S|-1)+|S|\times |ine|\)

合并的时候按照 \(|S|\) 启发式合并,容易发现这样复杂度一定不会有问题。假设合并 \(x,y\) 之后的集合编号定为 \(y\)

先把 \(point\)\(ine\) 无脑合并起来。

对于 \(v\in outp_x\) ,有 \(x\in inp_v\) ,需要改成 \(y\in inp_v\)\(v\in inp_x\) 同理。

对于 \(z\in (inp_x\cap outp_y+outp_x\cap inp_y)\) ,需要进一步合并 \(y,z\) ,把这些点对存在一个队列里依次合并。

既然都启发式合并了,所以入队列的总点对自然应该也不会太多。

LOJ3276「JOISC 2020 Day2」遗迹

胡出正解了好激动

为了方便+能做,假设同一个数的两个分身是不同的,最后再乘 \(2^{-n}\)

先考虑怎样可以在不暴力模拟的情况下得到一个序列是否合法。

按照值域从大到小考虑,以 223311 为例。

先看到两个 3 ,那么右边那个保留下来,左边那个会变成 2 ;

然后有三个 2 ,仍然保留最右边的 2 ,其它 2 或早或晚都会变成 1 。

最后有四个 1 ,保留最右边的 1 。

然而这样还是不太好计数。

转换成从右往左考虑,维护 \(vis_x\) 表示数 \(x\) 是否有被定下来位置。加入一个数 \(y\) 的时候 while (vis[y]) --y; ,即可知道它会变成什么,或是被删掉。

但是显然 DP 的时候也还是不能把 \(vis\) 存下来。

注意到我们最主要关心的是 \(vis\) 的极长前缀 1 的长度,所以不妨只记这个东西。

那么当前位置要被删掉的时候就可以转移了,而如果当前位置要被加入的话,就枚举加入之后极长前缀 1 的长度会变成什么,计算贡献。

https://www.cnblogs.com/dysyn1314/p/12877113.html 神仙dy的博客讲得更加详细。

LOJ3277「JOISC 2020 Day3」星座 3

我也忘记怎么做了……建出笛卡尔树之后线段树合并乱搞一通好像就行了。

https://loj.ac/submission/772893

LOJ3278「JOISC 2020 Day3」收获

想到思路不难,不过实现也有一些细节。

显然果树之间两两独立,而一棵果树被某个人摘了之后下一次被摘显然是这个人往后第一个距离超过 \(C\) 的人。这样连一条边即可连出一个基环内向树。

对于树上的情况,相当于询问子树内某个权值小于等于某个数的果树个数,随便做。

对于环,可以先把环上的一条边断掉,算出不经过这条边的贡献,然后把所有果树都移到这条边指向的点。

此时的询问就可以被看做一个二维数点(走过来的时间不能太长,然后按照模环长的余数分类),离线一下即可 \(O(n\log n)\)

https://www.cnblogs.com/dysyn1314/p/12582983.html 神仙dy的博客讲得更加详细。

UOJ509. 【JOISC2020】迷路的猫

关于LOJ,它咕了

竟然又直接搞出正解了,爽啦

对于 \(A\ge 3\) 的情况,有这么一种构造方法:

把 BFS 树建出来,那么我们想要每个点每一步都能使得 \(dep=dep-1\)

既然有三种颜色,那么可以搞出这么一种大小关系: \(0<1,1<2,2<0\) ,然后对于每个点,把能走的标成一种颜色,不能走的标成比它大的一种颜色。

其实就是把颜色标为 \(dep_x\%3\)

然后只考虑 \(A=2,m=n-1,B\ge 6\)

如果每一个点的儿子数量都不是 1 ,那么容易发现只需要按深度黑白染色即可。

所以考虑链应该怎么做。

把链上的边循环染色,一个循环节为 BBWBWW

盯着这个串 BBWBWWBBWBWWBBWBWWBBWBWW...

如果起始点旁边是 WWBB ,那么沿着某一个方向连走两步,就可以确定哪一边是根的方向了。

否则,先往 B 走一步。如果此时走到了 BB 那么同样按照上面的方法就可以知道哪一边是根了。

否则再往同样的方向走一步,那么可能走到 WWBW ,也就知道哪边是根了。

知道哪边是根之后就很好搞定了,不走回头路即可。此时多走的步数恰好最多为 6 。

怎样套回到一棵树上呢?

设根(即终点)是 \(x\) ,那么显然根的每一棵子树的染色方案互不影响,设某一个儿子是 \(y\)

如果之前没有定下来 \((x,y)\) 的颜色,那么不妨钦定它是 B 。以下都假设 \((x,y)\)B ,如果是 W 就把循环节循环移位一下变成 WWBBWB ,显然前面的讨论是不变的。

考虑 \(y\) 有几个儿子:如果有超过 1 个,那么把这些边全都变成 W ,然后发现只要能走到 \(y\) 就可以走到 \(x\) ,所以可以递归 \(x=y,y=son\)

否则,设 \(y\) 往下第一个不止一个儿子的点是 \(z\) ,那么把 \(x\to z\) 这一段按照链的方法染色,\((z,son_z)\) 的颜色设为 \((fa_z,z)\oplus 1\) ,然后递归。

分析一下正确性:如果出生点是 \(z\) 或是 \(z\) 的子树,那么直接可以往链上走,然后不走回头路一路走到 \(x\) ,且没有多余步数;否则如果出生在链上,就可以按照链的做法做,同样能找到 \(x\)

显然如果链不够长,在走链的过程中一不小心走到了 \(x\)\(z\) ,那么也可以直接确定根的方向。

于是做完了。

LOJ3280「JOISC 2020 Day4」首都城市

不能想太多,暴力一点就赢了……

考虑建图: \(x\to y\) 当且仅当 \(x\) 城市的小镇组成的虚树中包含 \(y\) 城市的小镇。那么缩点之后就是出度为 0 的强连通分量大小的 \(\min\)

这个建图用倍增优化即可。

LOJ3281「JOISC 2020 Day4」传奇团子师傅

一开始胡了个二分图匹配,然后发现白色可能会被用多次,然后就自闭了……

乱搞即可。不想学了。

LOJ3282「JOISC 2020 Day4」治疗计划

想象一下按照时间顺序模拟的情况:会有若干个健康区间,每次加入区间的时候可能会合并,然后随着时间往后推左右端点往里缩。

然后……感受一下就可以得到这么一个做法:不再按时间模拟,而是从左往右加区间,最后要把区间连成 \([1,n]\)

两个区间可以并在一起当且仅当 \(r_i+1\ge l_j+|t_i-t_j|\)

然后类似最短路转移。令边权为指向的点的点权。

为了优化最短路的过程,把绝对值拆开,把点按 \(t_i\) 排序,然后用两棵线段树分别维护区间中 \(l_j\pm t_j\) 的最小值和取到最小值的位置,转移的时候把一整个前缀中合法的点都转移掉,并在线段树中删除。

一个点只会被转移一次、删一次,所以复杂度 \(O(n\log n)\)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章