JOI2020

JOI2020

代码自己去LOJ看

要在日本多好,JOI Final比CSP-S简单.jpg

只不过是长的领带

显然的贪心是删掉某一个之后将两个序列排序一一匹配。所以排序之后维护\(A\)序列的一段前缀匹配\(B\)序列长度相等的前缀的奇怪度和\(A\)序列的一段后缀匹配\(B\)序列长度相等的后缀的奇怪度就可以快速得到删掉每一个位置之后的奇怪度。

JJOOII 2

设左端点为\(p\)的包含"J...JO...OI...I"、"O...OI...I"、"I...I"(省略号表示对应字符有\(K\)个)作为子序列的字符串的最小右端点为\(f_p,g_p,h_p\),按照\(h,g,f\)顺序转移,转移时从后往前扫,用些东西维护当前位置向后遇到的第\(K\)个'J'、'O'、'I'的位置。

集邮比赛 3

暴力DP:设\(f_{i,j,k,0/1}\)表示在起点的逆时针方向走过\(i\)个收集点、顺时针方向走过\(j\)个收集点、经过\(k\)个时刻、现在在起点逆时针方向的第\(i\)个收集点或顺时针方向的第\(j\)个收集点,这样的状态下最多能收集多少邮票。转移考虑走到起点顺时针或逆时针方向上的下一个收集点。

\(k\)很大,不过可以发现\(f_{i,j,k,0/1}\)的值很小,同时在值相同的情况下\(k\)一定越小越优,所以改良一下:设\(f_{i,j,k,0/1}\)其中\(k\)表示收集了\(k\)张邮票,其余意义一致,其值表示满足该条件情况下的最小用时,转移同上。答案就是存在有意义的\(f_{i,j,k,0/1}\)的最大的\(k\)

奥运公交

直接枚举换边暴力不太行,但是发现点数远小于边数。这启发我们从枚举点的思路出发考虑如何换边。枚举我们将要换的边的起点\(u\),考虑\(1\)\(n\)\(n\)\(1\)的路径的可能情况。\(1\)\(n\)\(n\)\(1\)实际上是一样的,下面仅对\(1\)\(n\)进行说明。不妨假设换的边是\((u,v)\),那么有以下若干情况:

  • \(1\)\(n\)根本没经过\(u\)
  • \(1\)不经过\((v,u)\)边走到\(u\),然后从\(u\)走到\(n\)
  • \(1\)经过\((v,u)\)走到\(u\),然后从\(u\)走到\(n\)

为了计算以上信息,我们需要求出:

  • \(1\)\(n\)不经过\(u\)的最短路;
  • \(1\)\(u\)的最短路;
  • \(u\)\(n\)不经过\((u,v)\)边的最短路。

看到第\(3\)个条件,好像要对于每一条边跑最短路,但实际上没有必要。我们可以在忽略所有\(u\)的出边的情况下跑出\(1\)到其它点、其它点到\(n\)的最短路。

那么对于\(1\)情况可以直接计算;对于\(23\)情况可以求出到达\(u\)的最短距离,而对于从\(u\)\(n\)不经过\((u,v)\)的最短路,相当于把其他\(u\)的出边加上。可以通过最短路求出从\(u\)的每一条出边出发到达\(n\)的最短距离并记录最小值和次小值,如果翻转了最小值对应的边就用次小值贡献,否则用最小值贡献。

注意到图中点数小而边数大,可以使用\(O(n^2+m)\)的朴素Dijkstra,复杂度\(O(n^3+nm)\)

火灾

做出这个题的时候感觉自己太恐怖了(雾

首先将询问变为前缀相减并离线,那么询问变成了二元组\((P,T)\)表示对长度为\(P\)的前缀在\(T\)时刻进行询问。

\(S_{i,j}\)表示在\(i\)时刻\(j\)位置的火势,考虑一个位置\(i\)的初始火势\(S_i\)\(R\)\(0\)不断变大时对序列的影响。它在\(1\)时刻会覆盖\(i+1\)\(2\)时刻会覆盖\(i+2\)、……直到某一个时刻\(t\)覆盖了\(i+t\)之后发现\(S_{t,i+t+1}>S_i\)然后贡献停止。将时刻和覆盖的位置看做一个点的横纵坐标,它们恰好落在一条线段上。

如果转成坐标系上的问题,覆盖不那么好做,而求和是比较熟悉的数点问题似乎更好做。考虑差分,如果\(S_i\)\(t\)时刻覆盖了\(j\),那么认为\(S_{t,j}\)\(t\)时刻增加\(S_i - S_{t-1,j}\)。那么位置\(i\)的贡献就可以表示成若干个四元组\((i,L,R,\Delta)\)表示\(\forall j \in [L,R]\)\(S_{j-i,j} = S_{j-i-1,j} + \Delta\)。现在问题变为有若干条线段、每条线段对其经过的所有整点加上一个权值,多次询问横纵坐标小于等于某个值的所有点的权值的和。

考虑如何处理出四元组。从右往左维护\(S\)的递增单调栈,那么加入\(S_i\)时会pop掉若干位置,\(i\)就会覆盖这些位置所覆盖的区间,且每段区间增量一致,可以得到等量四元组。这样可以得知四元组数量是\(O(n)\)的。注意到\(S_i\)覆盖的区间连续,所以可以对\(i\)位置的所有四元组的\(\Delta\)差分,并将左端点全部设为\(i+1\),这和原来是等价的。这样我们可以记修改为三元组\((i,R,\Delta)\),对应上述四元组\((i,i+1,R,\Delta)\)

当然直接数点还是不行,不妨考虑修改\((i,R,\Delta)\)对询问\((P,T)\)的贡献\((i < P)\),是\(\min\{R-i,P-i,T\} \times \Delta\)。接下来就是套路:将\([1,P]\)分为\([1,P-T-1]\)\([P-T,P]\),前者满足\(T<P-i\),后者满足\(T \geq P-i\),所以这两段区间内只需要考虑两个值取\(\min\)

对于\([1,P-T]\)区间贡献是\(\min\{R-i,T\}\)。我们可以以\(R-i\)作为下标,用树状数组维护当前加入的所有直线的\((R-i) \times \Delta\)\(\Delta\)的前缀和。对于一次询问我们就查询\(\leq T\)的位置的\((R-i) \times \Delta\)的和和\(>T\)的位置的\(\Delta\)和就可以算出贡献;对于\([P-T+1,P]\)先转换成前缀相减形式,然后同理维护若干个树状数组。

复杂度\(O(n \log n)\)但是一个询问最多要拆成\(6\)个还要维护好几个树状数组所以跑起来还是比较慢的。

猜你喜欢

转载自www.cnblogs.com/Itst/p/12296707.html
今日推荐