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;
}
posted @ 2026-09-09 20:28  GCSG01  阅读(9)  评论(0)    收藏  举报