24.07 做题记录
24.7 降维技巧
约定
diff=1 大水题 黄以下 一眼切
diff=2 easy 下位绿及黄 能切
diff=3 medium 特殊的黄;绿;较简单的蓝 可能需要题解提供一步
diff=4 hard 蓝色+ 需要题解
diff=5 不可做题 紫色+ 做不了
前缀和/差分
P1115 最大子段和
diff:1
前缀和板子。
P3406 海底高铁
diff:1
注意读题。前缀和板子。
看好数据范围
P2671 [NOIP2015 普及组] 求和
diff:2.5 tag:前缀和 性质
难点在于读题。
\((x,y,z)\) 表示的 都 是编号。如果读对了题会发现 \(y\) 没用。
由 \(2y=x+z\) 可以发现 \(x,z\) 奇偶性相同。将奇偶不同的编号分开排序。
按照颜色第一关键字,大小第二关键字排序并前缀和即可。
"写的是题解的三倍,还多一支 \(\log\),附赠一堆细节"
P1314 [NOIP2011 提高组] 聪明的质监员
tag:二分 前缀和
你说得对,但是当答案可能超过 int 时最小值初始化应为 LONG_LONG_MAX 而不是 INT_MAX。
二分 \(W\) 对于每个不同的 \(W\) 处理一次 \(w_i\ge W\) 的前缀和,复杂度就是对的了。
注意二分返回 true/false 的条件,当 \(s>ans\) 时 返回 false。
P1083 [NOIP2012 提高组] 借教室
我会线段树。
题意即为 \((+,\min)\) 线段树。
注意线段树的 add 函数改没改
P2367 语文成绩
差分板子。
P2882 [USACO07MAR] Face The Right Way G
diff:3 tag:贪心 细节
为什么从前往后看到方向朝后的就转回去是对的?
我们注意到把一个点转两次等于啥也没干 可以模拟得出贪心正确性。
优化简单于贪心。xor 差分维护当前是否转向即可。
注意代码细节,差分的下一个数是 j+i 没有 +1!
高维前缀和/差分
P2004 领地选择
diff:1
板子题。但是写对板子。
P3397 地毯
diff:1
板子。
P2280 [HNOI2003] 激光炸弹
diff:1.5
坐标有0 坐标有0 坐标有0 坐标有0。记得对所有的数组偏移 \(1\),不然 91 pts。
P1719 最大加权矩形
diff:1
板子。建议你谷课程题单减少板子题数量。
P3017 [USACO11MAR]Brownie Slicing G
diff:3.5 tag:贪心 性质 二分 前缀和
USACO 首先考虑贪心
二分答案,对于每一次 check,我们可以贪心。
具体的,先满足列的条件。如果该列在满足 \(\ge x\) 情况下无法 \(\ge b\) 块,那么加一行,注意每一块的范围是以 (上次分割行,上次分割列) 和 (枚举点行,枚举点列) 形成的长方形而不是一行连着取。是否满足条件即是否 \(\ge a\)。
前缀和即可。
因为少写 else 多交两发。
[ARC100E] Or Plus Max
diff:4 tag:sosdp 高维前缀和
考虑对每个 \(k\) 分开计算,即令 \(A_k=\max_{i\operatorname{or} j=k} a_i+a_j\),则 \(ans_k=\max_{i=1}^k A_i\)又注意到上式即 \(A_k=\max_{i,j\subseteq} a_i+a_j,ans_k=\max_{i=1}^k A_i\) 这是由于或运算的不减性。该转化是进行 sosdp 的前提。
事实上该问题可以枚举子集,\(O(3^n)\),事实上我们可以非容斥计算前缀和。
e.g. 三维前缀和
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
a[i][j][k] += a[i - 1][j][k];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
a[i][j][k] += a[i][j - 1][k];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
a[i][j][k] += a[i][j][k - 1];
sosdp 是一个每一维度长度都为 2 的高维 dp。
for(int i=0;i<=n-1;i++)
for(int j=0;j<=(1<<n)-1;j++)
if((1<<i)&j)
m[j]=m[j]+m[j-(1<<i)];
这段代码中 \(j\) 在 \(j-2^i\) 的上一层,从 0 开始,建议背过。
从 dp 角度理解:
定义 \(f_{i,r}\) 表示当前处理到二进制最后 \(i\) 位,状态为 \(r\) 的情况,当枚举 \(i+1\) 位时,若 \(r\) 即当前状态为 1,就从 \(f_{i,r},f_{i,r-2^i}\) 转移,分别表示有/无该位的情况并合并,否则从 \(f_{i,r}\) 转移即可。实现上,我们滚动掉第一维。
求超集仅需在 if 中加入一个 ! 取反即可。
树上差分
P3128 [USACO15DEC] Max Flow P
diff:2
我会树剖。
P3258 [JLOI2014] 松鼠的新家
diff:2
我也会树剖。
P2680 [NOIP2015 提高组] 运输计划(todo)
todo
P1600 [NOIP2016 提高组] 天天爱跑步(todo)
todo
离散化
P1097 [NOIP2007 提高组] 统计数字
diff:1
板子。
P1955 [NOI2015] 程序自动分析
diff:2.5 tag:并查集 离散化
diff=2.5 而不是 2 的原因是写挂了若干发。
我们只需要判断是否在不相等时能否满足,原因是显然的——等式具有传递性,所以我们事实上只需要维护相等这一个并查集即可。
离散化写了要用。并查集要写 f[i]=i。
fun fact:洛谷 #2 #10 放反了,所以你如果没有离散化会 RE #2
P1052 [NOIP2005 提高组] 过河
diff:3 tag:dp 离散化
细节题。
显然可以进行 dp。有转移式子:
其中 \(p_i\) 表示是否该位置有石子。
由于 \(1\le L \le 10^9\),并且答案与跳的石子数量无关,我们需要且必须进行离散化,由于我不想做数学题,所以我们不卡离散化常数,\(\operatorname{lcm}{1,2,\cdots10}=5040\),所以如果两个石子的距离超过 \(5040\),我们直接将距离 \(-5040\) 即可。
细节的原因是跳到或跳过 \(L\) 时都可以产生贡献,注意统计答案。
题目不保证输入的 \(M\) 有序,否则可以拿到 \(8\) pts 的好成绩。
双指针
P1102 A-B 数对
diff:1
你谷题单能不能少点__。
P3143 [USACO16OPEN] Diamond Collector S
diff:2 tag:双指针 贪心
我们双指针枚举分界线左边的贡献,具体的,每次超过 \(k\) 时,左指针右移,否则右指针右移;右边的贡献直接取分界线到最后的后缀 \(\max\) 即可。
注意边界值的处理,挂了 3 发。
P4653 [CEOI2017] Sure Bet
diff:3 tag:贪心 双指针
三分神秘看不懂。考虑贪心。
显然要从价值高的往价值低的拿,当一组的收益小于另一组时,继续拿另一组显然对于答案是不优的,所以贪心策略即为排序后,拿收益较小的一组的最大值。
不是啥传统意义上的尺取法双指针。
注意可以不取,否则会 \(97\) pts。细节。
P1311 [NOIP2011 提高组] 选择客栈
diff:2.5 tag:贪心
注意做题之前要读题。注意做题之前要读题。注意做题之前要读题。注意做题之前要读题。注意做题之前要读题。
考虑一个桶,表示在第 \(i\) 个元素前的相同颜色元素个数,如果当前位置的元素 \(<p\) 我们再对这个桶计入上一个 \(<p\) 的位置到该处这段位置的元素,并将当前元素的颜色所属的桶的大小计入贡献,否则,仅将当前元素所属的桶的原大小计入贡献。
为什么这么做是对的,因为不要求两个人住的地方的颜色是连在一起的,所以只需要看两个人所处的位置,不需要考虑其他因素。所以注意读题。
P1638 逛画展
diff:2
尺取法板子,但是我不会。
先推右指针,记录区间内每种颜色出现次数,满足条件的情况下推左指针,一直到有一种颜色出现次数为 \(0\) 时,推右指针。以此继续即可。
代码卡了一天。
for(;j<=i;j++)
{
t[a[j]]--;
if(t[a[j]]==0)
{
cnt--;
if(i-j+1<minn)
{
minn=i-j+1;
aa=j,bb=i;
}
j++;
break;
}
}
注意两个细节:break 的位置和 j++。
特别的,如果写双指针不建议写成 for 循环的形式,因为指针变量的自增很有可能在 break 时少触发一次导致错误,且这个很难调。
UVA11572 唯一的雪花 Unique Snowflakes
diff:1.5
尺取法板子,和上一题差不多,如果合法右移右端点,否则右移左端点。
没有代码。因为上不去 UVA。
[ABC098D] Xor Sum 2
diff:2.5 tag:xor
典中典 \(\operatorname{xor}\) 性质题,由于异或是不增的,所以 \(\sum_{i=l}^r a_i=\operatorname{xor}_{i=l}^r a_i \Longleftrightarrow \forall i a_{i}+a_{i+1}=a_{i}\operatorname{xor}a_{i+1}\) 也就是这任意两数二进制位不能有同为 \(1\) 的情况。
也就是异或是不进位二进制加法。
写个前缀异或和然后跑双指针即可,注意 ans 的贡献到底两头是取不取,别挂细节。
P1083 [NOIP2012 提高组] 借教室
diff:1
我会线段树。空间开足了记着。
CF939E Maximize!
diff:2.5 tag:贪心
性质题。
由于给定的数是递增的,所以新数一定要放入。
小于集合平均数的数放入一定更优。
尺取法维护小于集合平均数的数即可。
单调栈
P2866 [USACO06NOV] Bad Hair Day S
diff:2
单调栈板子,但是我也不会。
维护一个单调上升的栈,栈内的奶牛均可以看到最新入栈的奶牛。每次对答案贡献统计栈内的元素数量即可。
不开 long long ___。
P3467 [POI2008] PLA-Postering
diff:3
主要是谜语人题面。覆盖的意思是想象你面前横着有一排建筑要把面向你那个面覆盖而不是其它的。
如果两个建筑高度不同,无论如何都要用两张,可以少用一张海报当且仅当两个建筑高度相同且中间的高于它。
由此,可以维护一个单调严格递增栈,加入元素时如果最后出栈的元素等于当前元素,\(ans\leftarrow ans-1\)。
P1950 长方形(todo)
todo
单调队列
P1886 滑动窗口 / P2032 扫描 / P2251 质量检测 / P1440 求m区间内的最小值
diff:1.5
单调队列板子,使用 deque 实现。
怎么这么多板子。
P2880 [USACO07JAN] Balanced Lineup G / P1816 忠诚
diff:1
ST 表板子。
P2216 [HAOI2007] 理想的正方形 (todo)
diff:3
二维 ST 表/单调队列板子。
没写。
P1714 切蛋糕
diff:2
单调队列优化 dp 板子,远古时期写的题。
具体的这题需要先前缀和再上板子。
P1725 琪露诺
diff:2.5
多了 0.5 是因为写炸了若干发,被琪露诺附身了(悲)。
使用了题解区没人用的坐标偏移,注意偏移要偏移全了。
挂 hack 的原因是要将初值赋值为负无穷,分清下标和值。
P2627 [USACO11OPEN] Mowing the Lawn G
diff:2
也是远古写的题了,好像也是维护个前缀和再上板子的类似状物。
P2034 选择数字
diff:3
正难则反!
不妨把问题转化成在 k 个数内选一个使得和最小。
写坐标偏移很多细节所以不要写。较好的写法是每次更新循环到的那个位置,队列的出队条件是 \(i-k\)。
P3800 Power收集
diff:2.5
由于坐标偏移的写法细节太多,所以写的时候一度 code diff >3 的。
其实就是跑 \(n\) 轮单调队列。
写挂点:小心负数下标;不要使用坐标偏移;在原数组上 dp(f[x][y]=v);第二次循环仍从 j 开始;先出入队再算贡献。

浙公网安备 33010602011771号