2025CSP-S模拟赛4 总结
不能说炸,一是代码能力还要再练,二是这回 T2 屁都没写,三是 T2T3 有一群桂做过原导致有些zwh9997777分有点小高,四是 mol。
除了 T1 45pts 都是 0...
T1 序列问题
赛时
考虑 \(dp_{i,j}\) 表示到 \(i\) 时留了 \(j\) 位的最大答案,转移是 \(dp_{i,j}=\max (dp_{i,j},dp_{i,j-1})\) 然后转移完后如果 \(a_i<=i\) 那么再让 \(dp_{a_i,j}=dp_{a_i-1,j}+1\)。
然后赛时觉得这玩意大有搞头,滚完之后作为全场唯一的想到了火事的人,一定很厉害吧😎!
虽然但是火事的状态不带修,这题这么说还是加强版。
然后就被硬控了 1h 回忆火事……
正解
考虑 \(dp_i\) 表示到 \(i\) 时 \(i\) 必留的权值,则有:
其中 \({j<i~\cap ~a_j<a_i~\cap~ a_i-a_j<i-j}\)。
考虑优化,注意到当后两个条件满足时,第一个肯定也满足,而第三个条件又可写作 \(a_i-i<a_j-j\) 于是将序列按照 \(a_i\) 排序后对 \(a_i-i\) 跑最长不降子序列即可。
T2 钱仓
赛时
刚开始通读题的时候以为“mol”是什么打炸的 \(\LaTeX\) 然后一直在等 bobo 修题面,然后等 T3 打完回来猛然醒悟“mol”啥也不是时离结束还有 30min,想到正解打伪了然后以为做法是错的遂放弃。
还是建议题目不要用奇怪的自定义量词。
正解
解法来自传奇贪心代师Zpn。
考虑先断环为链后倍增一下,然后从后往前扫遇到零就加入队列中,对于每个非零位如果队列不为空就把最远的给填直到把自己用完或者清空了队列,对于任意 \(i\le n\) 如果当前队列为空或最近的零 \(\ge i+n\) 就可以更新答案。
花絮:
这个做法我和Zxy打的时候不约而同的把
q[r]>i+n
打成了q[l]>i+n
,这样判的就是最远的零而非最近的零但还是能过。Zxy认为是数据过水没管了,然后我创造性的直接给这个删了让只有队列为空才能更新,还是过了😱。
然后我认为是性质,叫Zxy讨论,我打对拍看数据是不是过水是Zxy直接发现了以下性质:
考虑一个合法区间它的数字和肯定刚刚好是 \(n\) ,只要给出去一块钱就会有零在区间中出现导致区间不合法,但如果区间外有零遍历区间时肯定会给出去,所以只有队列为空才能更新。
花花絮絮:
Zxy认为是卡常技巧想拿最优解然后给判断删了反而多跑 1ms🤣。
这题有点意思反常贴一下代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace AM{bool st;}
namespace I{
int n,c[200200],q[200200],sum[200200],l,r,ans=1e18;
string main(){
// freopen("barn.in","r",stdin);
// freopen("barn.out","w",stdout);cin>>n;for(int i=1;i<=n;i++){cin>>c[i];c[i+n]=c[i];}l=1,r=0;for(int i=2*n;i>=1;i--){sum[i]=sum[i+1];if(!c[i]){q[++r]=i;}else if(l<=r){while(l<=r&&c[i]){c[i]--;sum[i]+=(q[l]-i)*(q[l]-i);l++;}if(!c[i]){q[++r]=i;}}if(i<=n&&(l>r||q[r]>i+n)){ans=min(ans,sum[i]-sum[i+n]);}}cout<<ans<<'\n';return "点击输入标题";
}
}
namespace AM{bool ed;double kj(){return (&st-&ed)/1048576.0;}}
signed main(){cerr<<I::main()<<AM::kj();return 0;
}
T3 自然数
赛时
被这题草飞了,不知道为啥就一直在写 50pts 而忽略了 T2 的简单正解。
哦是因为“mol”啊 😅。
想了 1.5h 才考虑到 \(mex\) 不可能 \(>n\),1.5h 前疯狂重构。
受上次模拟赛启发拿几个数组记录了每个值域连续段的左右端点,几个大样例都过了。
赛后戏剧性的出分0pts,原因未知。
事实证明:只要你敢赌,分会让你哭。
正解
正解挺神奇的,考虑先将 \([1,1\sim n]\) 的 \(\text{mex}\) 预处理出来,然后用线段树来维护 \([l,l\sim n]\) 的 \(\text{mex}\)。
令 \(nxt_i=j\) 表示与 \(i\) 最近的 \(j\) 使得 \(a_i=a_j\),当 \(l\) 向右移时,\(l\sim nxt_l\) 的大于 \(a_l\) 的 \(\text {mex}\) 都要改为 \(a_l\)。
然后这就是一个经典的区间推平操作,对于大于 \(a_l\) 的限制线段树上二分即可。
T4 环路
赛时
没看
正解
给他转成矩阵快速幂即可。