JOI2020题解
只不过是长的领带
显然最后一定是大的匹配大的,小的匹配小的。那么问题就是对于两个排好序的序列长度分别为(N+1,N)的(A,B)两个序列,求分别挖掉(A)中的每个位置的答案。这个东西可以通过维护前缀以及后缀的答案做到,复杂度(O(n))。
JJOOII 2
只要确定一个满足有(K)级JOI-串的区间就可以确定一个可能答案。
那么我们可以枚举这个区间的起始位置(i),维护三个指针(p1,p2,p3)分别表示([i,p1])中有(K)个J,((p1,p2])中有(K)个O,((p2,p3])中有(K)个I,那么(i)的贡献就是(p3-i+1-3 imes K),所有(i)的贡献取个(min)就好了,复杂度(O(n))。
集邮比赛 3
考虑dp。因为时间较大,所以我们必须让状态里面不包括时间。
设(f[i][j][k][0/1])表示目前走过([1,i],[j,N]),且目前收集了(k)张邮票,在(i/j)的最小时间,那么最终答案就是所有合法状态中最小的(k)。
奥运公交
因为反转一条边对从(1 ightarrow n)和从(n ightarrow 1)的贡献其实是独立的,所以我们只需要考虑(1 ightarrow n)的贡献即可。
按照加删边最短路的套路,我们分别跑一遍正图上以(1)为起点的最短路求出(dis1[i]),一遍反图上以(n)为起点的最短路求出(dis2[i]),如果一条反转的边((u,v))不在这两遍(1
ightarrow n/n
ightarrow 1)最短路中,那么可以直接通过比较(dis1[v]+dis2[u]+c_{(u,v)}+d_{(u,v)})与原最短路的答案得出贡献。
如果((u,v))在原最短路中,考虑这样的边数是(O(n))级别的,我们可以重新跑最短路,此时使用不加堆优化的(dijkstra)可以做到单次(O(n^2))。
火灾
以位置为(x)轴,时间为(y)轴建立坐标系,将询问拆为两个前缀相减,那么我们就是要求某个时间某一行的某个前缀和。
因为每次一个位置的变化都是一个(a
ightarrow b)的形式,而这样本质不同的(a
ightarrow b)实际上不超过(n)种,那么我们一次改变就是对平面某块区域加上(b-a)。
求出(L_i=max{j|j<i,S_j>S_i},R_i=min{j|j>i,S_j>S_i}),那么上述(a
ightarrow b)实际上就是(S_i
ightarrow S_{L_i})。
考虑这种变化发生的时间与范围,那么可以知道,对于(forall jin[i,R_i)),上述过程会在(j-L_i)时刻发生,使(p in [i,R_i), t ge p-L_i)的(S_p(t))加上(S_{L_i}-S_i)。
可以发现我们贡献的范围是个直角梯形,我们将这个直角梯形差分,令三元组((x,y,w))表示经过((x,y))且斜率为(1),从横坐标为(x)开始的上方区域全部加上(w),那么对于一个位置的贡献可表示为((i,i-L_i,S_{L_i}-S_i),(R_i,R_i-L_i,S_i-S_{L_i}))。
考虑一个修改((x,y,w))对一个询问((p,q))的贡献((pgeq x,qgeq y))就是(w imes min{p-x+1,q-y+1}),意味着一个点在((x,y))上半部分和下半部分分别是算不同的两个贡献((-x+1 ext{or} -y+1) ),我们可以考虑将询问及修改离线,按照每个点的截距排序,那么每条直线的变化就可以通过扫描线很好的表示出来,然后可以分别算(-x+1,-y+1)两种类型的贡献。那么我们对于每种类型,维护一个(sum w)以及一个(sum w imes i)的树状数组即可维护(具体实现详见代码,我讲不清了)。