正睿暑期集训7B

数据结构

穿越时空

一个带点权的树,你可以从任意节点开始,每次可以往任意一个祖先跳或者往任意一个子树节点跳,一个节点只能被跳一次,最大化经过的节点的点权和。\(n\le 10^5\)

必然是从 \(u\) 跳到一个祖先,才能继续转化到另一个子树中。设 \(f(u,j)\) 表示在 \(i\) 的子树内,有 \(j\) 次重新选择起始点(然后跳到子树中)的次数机会。考虑用类似树形背包的转移。\(f(u,j)=w_u+\sum_{\sum c=j+1} \sum_{v\in son_u} f(v,c_v)\)

发现这是若干个子树值的一个 max 卷积,所以 \(f(i,j)\) 是关于 \(j\) 的一个凸函数【凸函数做max卷积还是凸函数】。【两个凸函数做max卷积的差分数组相当于两个凸函数的差分数组做归并排序】。考虑用数据结构维护凸函数的差分数组。然后我们每次的时候要把第一个和第二个给加起来(因为 \(sum=j+1\) 所以要向左移动)(即pop掉第一个第二个,然后加起来再加上 \(w_i\) 再 push 进去),对于 \(+w_i\),只要给第一个加一个 \(w_i\) 即可。可并堆/启发式合并即可。

*BZJ3252 攻略(自己练手的题)

模板题
https://www.luogu.com.cn/blog/forever-captain/solution-bzoj3252

APIO2016 烟火表演

考虑暴力,\(f(i,j)\) 表示 \(i\) 及其子树内的叶节点到 \(i\)的距离为 \(j\) 的最小代价。\(f(i,j)=\sum_v \min_{x\le j} f_{v,j-x}+|x-w_{u,v}|\)。我们发现这些都是下凸函数,然后min卷积,必然也还是凸函数【下凸函数min卷积,上凸函数max卷积是可行的,否则不可行】。所以 \(f(i,j)\) 关于 \(j\) 是凸函数。

然而我们发现绝对值函数的斜率边为 \(-1,-1,-1,...,1,1,1\),所以我们找到 \(f\) 的斜率为 0 的地方,将左边向左上平移然后接上一段斜率为 \(-1\) 的,然后删去右边并接上斜率为 \(1\) 的射线。考虑如何实现 DP 时的凸函数加法。我们发现凸函数斜率非常小,考虑用堆维护拐点(在斜率增加 \(x\) 的地方放 \(x\) 个拐点)。考虑如何看出斜率为0的部分:我们发现最后一条直线的斜率为儿子个数,于是我们pop儿子个数个拐点就行了,就可以得到那个代表斜率为0的拐点和代表斜率为1的拐点,将其横坐标+w即可。

长者

一个长度为 n 的排列,有些位置上的数字已经确定了,剩下位置上的数字不确定。你要确定剩下位置上的数字,让得到的排列的最长上升子序列长度尽量长。

这个排列只能限定你填的数和上面填的数互不相同,别的数相不相同不影响答案,因为最长上升子序列必须是不同的。

\(r_i\) 代表 \([1,i]\) 有多少空位,\(s_i\) 表示 \([1,i]\) 有多少个数没有出现。则有 \(f_i=\max_{j<i,a_j<a_i} f_j+\min(r_i-r_j,s_{a_i}-s_{a_j})+1\)

考虑拆 \(\min\)。如果 \(r\) 的差比较小,相当于 \(r_i-s_{a_i}\le r_j-s_{a_j}\),于是我们设 \(c_i=r_i-s_{a_i}\),于是我们可以把它加进限制,然后三维偏序一下即可。

HDU 6800

一个二维点序列 (ai,bi),你需要把它拆成两个子序列,使得两个子序列中相邻两项的曼哈顿距离之和最小。

考虑DP \(f(i,j)\) 代表截止到 \(i\),另一个子序列的结尾是 \(j\)。然后转移的时候唯一一个需要考虑的是 \(f(i,j)\to f(i+1,i)\),即 \(f(i,i-1)\leftarrow f(i-1,j)\),这个可以设 \(g_i=\max_j f_j+s_{i-1}-s_j+w(i,j)\),拆掉 \(w(i,j)\) 的绝对值,(\(s\)\(w(i,i-1)\) 的前缀和)三维偏序即可。

序列

有 n 种物品,第 i 种物品第一次选择的收益是 ai,之后每次选择的收益都是 bi,代价始终为 ci。你需要求出在总代价不超过 m 下收益的最大值。有 Q 次修改,第 j 次修改会在第 i 次修改(i<j)的基础上修改一个物品的两类收益。你需要对于每次修改后输出答案。

普通 DP 比较容易,考虑先强制转移选一个 \(a_i\)\(f(i,j)\to fi,j+c_i\),然后普通背包 \(f(i,j)=max(f(i,j),f(i,j-c_i)+b_i)\),然后最后和 \(f(i-1,j)\)(不选)取 max。

?????????????????????????????????

P5163 WD与地图

离线,倒着做,然后搞线段树合并。难点在于怎么算什么时候缩起来。

考虑整体二分计算出每条边在哪个操作时被缩起来。对于一个时间轴,考虑一个mid,把出现时间<=mid的边加入跑tarjan,如果左边没有缩起来就扔到右边去,对于已经缩起来的点,用一个可撤销并查集维护一下。

Ynoi 镜中的昆虫

维护连续段(优化一下珂朵莉树),支持删除加入和求区间数字种类数,维护每个数上一次出现位置,然后就可以转化为二位数点,树套树搞一搞。

HEOI2016 排序

二分第 q 个位置的数,然后序列转化成01序列,然后线段树做。

  • 修改:强制在线实时询问

维护连续上升/下降段,用权值线段树维护,需要搞线段树分裂(每次排序的边上两个点),然后中间连续段线段树合并。

UOJ228

区间极差<=1时可以维护很多东西(通过维护最大最小值,多少个最大值etc),打个tag辨认出这样的区间即可;否则暴力地柜。

Ynoi2015 世上最幸福的女孩

正常维护需要求前缀最大值后缀最大值和区间最大值。比如前缀最大值。是 \(pre_i+i\times t\) 的形式。凸包!答案必然在这样的一个上凸壳上。每次对于给定的T,我们在凸包上二分一下斜率就可以找到切点了。那区间最大子段和的凸包怎么弄呢?我们发现合并前缀和后缀是一个max卷积!归并排序一下即可。

wzy:原题是各种卡空间卡时间不要去管他,我看了下原题是什么四毛子,分成 \(n/\log_n\) 个块,很无聊,真的很无聊。

SDOI2013 森林

主席树,启发式合并

CTSC2018 混合果汁

对美味度排序,对于每个询问,二分答案,然后搞主席树,对美味度 \(\le mid\) 的选最便宜的结束。

P2839 [国家集训队]middle

二分答案。如果存在一个区间使得其中位数 \(\ge\) 这个二分的东西,代表可行,即把区间所有 \(<\) 的数变成-1,其他变成1,求区间和,看是否 \(>0\)。考虑前缀和 \(p\),你希望让 \(p_r\) 尽可能大然后 \(p_{l-1}\) 尽可能小。用主席树去在上一个版本上进行后缀加(因为是前缀和),然后后缀减和求最大值可以用主席树维护。

HDU5756

好点在dfs序上一定是最多 \(k+1\) 个区间,考虑每个区间的贡献。

对于每个p,主席树维护他与其他点的距离的最值与和。

posted @ 2021-08-03 13:22  LarsWerner  阅读(116)  评论(0编辑  收藏  举报