2026/09/09 考试总结
省流:码力惊人,要减少 AI 调题了qwq
T1
用了 40min得到了:
注意到有值的数字对个数是 \(nlogn\) 的,如果我们能通过 \(nlogn\) 或 \(n\sqrt{n}\) 的时间处理出这些数字对,
则可以用可持久化线段树维护每个后缀的前缀答案(及固定 i,维护 j>=i 的所有答案),
那么现在的问题在于如何快速找到这些数字对
但是卡在拓展出数字对这一步了。
具体来说,注意到和为 \(2^k\) 的一组数一定是合法解,
在此基础上,将两个数同时乘上同一个值显然对答案没有影响。
我应该能看出来的,只是一直想着系数为 \(\frac{2^k+1}{2^k-1}\) 了awa
然后合法数对的总数是 \(nlogn\) 级别的,预处理出来。
对于询问,离线下来做带权二维数点即可。(主席树好像会被卡?)
T2
简单势能,但我真的要练习码力了。
\(\lfloor\sqrt{x}\rfloor\) 只会有 \(\sqrt{x}\) 种取值,因此每个数对答案的贡献之多改变 \(\sqrt{x}\) 次,
又有修改次数不多于 \(3\times 10^4\),直接上势能。
记录每一个数距离贡献发生改变还要加几次 \(1\),维护区间最小的这个值。
并在会发生改变时暴力递归找到这个数修改。
实现的话建议将修改拆成 3 个函数,先对距离全局减 1,再全局寻找小于等于 1 的进行修改,
最后维护贡献和与答案。
T3
不错的 trick,场上没时间看题。
trick1 对于 01 序列的 lis,形如取 \(i\) 之前的所有 \(0\) 和 \(i\) 之后的所有 \(1\)。
转化 为记录所有 \(1\) 的数量,将 \(1\) 看成 \(-1\),\(0\) 看成 \(1\),问题变为求最大前缀(不翻转的情况下)。
考虑翻转操作所带来的影响,若我们选取了 \(k\) 个互不相交的区间,则一定可以通过 \(k\) 次操作将它们和前缀拼到一起(证明显然)
那我们现在就需要维护区间最大子段和并支持区间取反,用线段树可以快速维护。
代码片段:
void push_up(node&p,node x,node y){
p.s=x.s+y.s;
p.lp=max(x.lp,x.s+y.lp),p.lpR=x.lp>=x.s+y.lp?x.lpR:y.lpR;
p.rp=max(y.rp,y.s+x.rp),p.rpL=y.rp>=y.s+x.rp?y.rpL:x.rpL;
p.tp=max({x.tp,y.tp,x.rp+y.lp});
if(p.tp==x.tp) p.tpL=x.tpL,p.tpR=x.tpR;
else if(p.tp==y.tp) p.tpL=y.tpL,p.tpR=y.tpR;
else p.tpL=x.rpL,p.tpR=y.lpR;
p.ln=min(x.ln,x.s+y.ln),p.lnR=x.ln<=x.s+y.ln?x.lnR:y.lnR;
p.rn=min(y.rn,y.s+x.rn),p.rnL=y.rn<=y.s+x.rn?y.rnL:x.rnL;
p.tn=min({x.tn,y.tn,x.rn+y.ln});
if(p.tn==x.tn) p.tnL=x.tnL,p.tnR=x.tnR;
else if(p.tn==y.tn) p.tnL=y.tnL,p.tnR=y.tnR;
else p.tnL=x.rnL,p.tnR=y.lnR;
}

浙公网安备 33010602011771号