CSP-S2024游记
CSP-S2024游记
考场:中山市纪念中学旧科学馆304一号座位。很快便开考了。发现键盘卡卡的,有点想找老师换,但是看到 T1 后兴奋的把这事给忘了。果然和预想的一样:唐题。
然而我的脑子在那时也被唐题感染变唐了,写了一种不好的写法,很快便过了大样例。思路大概是:排序不影响,数字实际大小不影响,故离散化后排个序双指针模拟。
然后开 \(T2\),感觉 \(T2\) 很简单的样子,然后又因为考前做了 导弹拦截 的缘故,误以为一二两问分开给分。于是自信开题。
大概过了好一会写完了第一问,于是想弃掉不好写的第二问先开 \(T3\) 乘胜追击。紧接着便是我的破防路程,因为我惊奇的发现:不!是!分!开!给!分!。那也就意味这我有两条路:一条是放弃先前耗费的时间,去做一道可能很难我做不出来的题。另一条是继续磕 \(T2\)。
这时我的原计划被打乱,慌慌张张的去看了 \(T3\),一时间没有什么好的想法,感觉好像可以 \(O(n^2)\) ,脑子也糊了一个看起来有模有样的转移方程,但是简单的思考过后认为做出来很玄(我在 \(OI\) 上并不是特别自信)。于是决定磕 \(T2\),因为我认为,\(T2\) 做出来第二问,我的 \(S\) 组就比较稳妥了,剩下的时间就可以没有负担的冲难题。而且 \(200\) 分应该已经可以 \(1=\) 了。
随后我 \(T2\) 开始疯狂码代码。因为急于求成,中途遗留了很多小问题,导致了调试时间的进一步延长。此时我常有过弃掉 \(T2\) 的想法,但是在时间、自信心不足和即将到来的胜利的三重因素下,我迟迟不肯放弃 \(T2\)。终于在考试结束前的半个小时左右,我过了题面的样例。
此时的我心里仿佛落下了一块石头,于是测了其他的大样例。看起来一切正常,我差点以为自己拿到 \(200\) 了,但是对比代码告诉我,我输了。在不为认知的几个角落里,我的第二问与答案相差了 \(1\)。然后我更慌了,反复调试检查,但是无济于事。最后 \(5\)min,我只是安慰自己应该能骗到分的。
但是我不敢坐以待毙,连忙去看有没有部分分。然后极限润完 \(T3\) 的 \(20\) 分部分分和一半的 \(T4\) 模拟(然而时间已至,你可以想象我当时手在卡顿的键盘上打出残影的刺激感,一边写 \(T4\) 模拟一边对照题面的狼狈样貌,还有我检查freopen存文件夹的着急慌忙)。
赛后车上,我口糊出了 \(T3\) 正解,经确认无误。实现也很好写,于是急了,摊在座位上安慰自己。
分数
估分: \(100+0+20+0=120\)。
实际:\(100+30+20+0=150\)。
\(CCF\) 我表白你的垃圾数据!给我这个没过样例的人放了 \(30\) 分!\(CCF\),我喜欢你那水得不能再水的数据!之前我总骂你数据水,现在真严了又不高兴。\(CCF\),还好你是那么坚守本心,将这水数据的才能又发挥了一年!赞美 \(CCF\)!
这里再次吐槽一下考场键盘 连续两年都是这种僵硬的键盘了......
赛时代码
T1
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,r[N],t[N];
int num[N],s[N];
int main(){
freopen("duel.in","r",stdin);
freopen("duel.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>r[i];
t[i]=r[i];
}
sort(t+1,t+n+1);
int cnt=unique(t+1,t+n+1)-t-1;
for(int i=1;i<=n;i++){
r[i]=lower_bound(t+1,t+cnt+1,r[i])-t;
}
sort(r+1,r+n+1);
for(int i=1;i<=n;i++){
num[r[i]]++;
}
int mx=r[n];
for(int i=1;i<=mx;i++){
s[i]=s[i-1]+num[i];
}
if(num[1]&&num[2]==0){
cout<<n;
return 0;
}
int i=num[1]+1,j=1;
for(;i<=n;i++,j++){
if(r[i]==r[j]){
i=s[r[j]]+1;
if(i>n)break;
}
}
j--;
cout<<(n-j);
return 0;
}
T2
#include<bits/stdc++.h>
using namespace std;
/*记得删调试*/
#define lb long double
#define ll long long
int T,n,m,L,V;
const int N=1e5+10;
ll d[N],a[N];
ll v[N],p[N];
struct node{
lb l,r;//区间
int num;
}sp[N];//第i辆车在哪段区间超速
/*
1.挨个判断车有没有超速
2.如果有车只在一个站超速那么这个站绝对不能删除
3.ai>0,一超速后面都超速
ai=0,超速就一直超速,要不一直不超速
ai<0,倒着来,剩下一段到起点都超速
4.
*/
vector<int>G[N];
const lb c=0.00001;
void solve(){
cin>>n>>m>>L>>V;
for(int i=1;i<=n;i++){//清空
G[i].clear();
sp[i].l=sp[i].r=0;
sp[i].num=0;
}
for(int i=1;i<=n;i++){
cin>>d[i]>>v[i]>>a[i];
if(a[i]==0){
if(v[i]>V){
sp[i].l=d[i];
sp[i].r=L;
}
continue;
}
lb s=d[i]+(V*V-v[i]*v[i])/(2.0*a[i]);
//位移到这里刚好瞬时速度为V
if(a[i]<0){sp[i].l=d[i];sp[i].r=s;}
else{sp[i].l=s;sp[i].r=L;}
}//预处理每辆车超速区间
for(int i=1;i<=m;i++)cin>>p[i];
ll ans=0;
for(int i=1;i<=n;i++){
// cout<<i<<" "<<sp[i].l<<" "<<sp[i].r<<"\n";
bool f=0;
for(int j=1;j<=m;j++){
if(sp[i].l==0&&sp[i].r==0){
sp[i].num=0;
continue;
}
if(p[j]>=(sp[i].l-c)&&p[j]<=(sp[i].r+c)){
if(!f)ans++;//当前线段内出现了点,且还没算贡献
G[j].push_back(i);
f=1;//被覆盖过
sp[i].num++;
}
}
}
cout<<ans<<" ";
/*有一些线段,问哪些线段覆盖了给定的点,
然后删去未覆盖点的线段,再删去尽可能
多的点,使得剩下的每个线段都覆盖了点
如果一个点对应的所有线段都对应了其它点,
那么可以删掉这个点*/
ans=0;
for(int i=1;i<=m;i++){
bool f=1;
for(int s=0;s<G[i].size();s++){
//所有盖在这个点上的线段
int j=G[i][s];
if(sp[j].num==0)continue;
if(sp[j].num==1){
//线段盖了一个点,此时这个点不能删除
f=0;
break;
}
}
if(!f)continue;
for(int s=0;s<G[i].size();s++){
//所有盖在这个点上的线段
int j=G[i][s];
if(sp[j].num==0)continue;
sp[j].num--;
}
ans++;
}
cout<<ans<<"\n";
}
int main(){
freopen("detect.in","r",stdin);
freopen("detect.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--)solve();
return 0;
}
//1
//5 5 15 3
//0 3 0
//12 4 0
//1 1 4
//5 5 -2
//6 4 -4
//2 5 8 9 15
T3
#include<bits/stdc++.h>
using namespace std;
/*记得删调试*/
const int N=20;
int T,n,a[N],b[N],ans;
int main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ans=0;
for(int i=0;i<=(1<<n)-1;i++){
for(int j=1;j<=n;j++){
b[j]=(i>>(j-1))&1;
}
int R=0,B=0;
int res=0;
for(int j=1;j<=n;j++){
if(R>0&&b[j]==1&&a[j]==a[R]){
res+=a[j];
}
if(B>0&&b[j]==0&&a[j]==a[B]){
res+=a[j];
}
if(b[j]==1)R=j;
else B=j;
}
ans=max(ans,res);
}
cout<<ans<<"\n";
}
return 0;
}
注意到多测我喜欢把实现部分放到 solve 函数里,然而我留给 \(T3\) 的时间改变了我的这个习惯。
后话
这次 \(CSP\) 对我来说意义非凡,然而我还是考砸了。
其实我真正学习 \(OI\),或许是这个暑假。我很感谢我遇见的每一个人,我真的很喜欢 \(OI\)。
我曾有一个 \(NOIP\) 梦,只是我在最接近她的时候把她弄丢了。
由衷的希望大家不要重蹈覆辙。
彩蛋
\(CSP\) 过后约三天的某节美术课上,我翘课去机房 vp \(T3\),以下是一节课 \(40\)min 加下课 \(10\)min 写出的 \(AC\) 代码……
#include<bits/stdc++.h>
using namespace std;
int T,n;
const int N=2e5+10;
int a[N];
#define ll long long
ll f[N],s[N];
const int V=1e6+10;
int lst[N],lst2[V];
void clear(){
s[1]=0;
for(int i=1;i<=1e6;i++)lst[i]=lst2[i]=0;
for(int i=1;i<=n;i++)f[i]=0;
}
void pre(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
if(i>1){
if(a[i]!=a[i-1])s[i]=s[i-1];
else s[i]=s[i-1]+a[i];
}
if(lst2[a[i]]){
lst[i]=lst2[a[i]];
}
lst2[a[i]]=i;
}
}
void solve(){
clear();pre();
for(int i=2;i<=n;i++){
f[i]=f[i-1];
if(!lst[i])continue;
ll w=s[i-1]-s[lst[i]];
f[i]=max(f[i],f[lst[i]+1]+w+a[i]);
}
cout<<f[n]<<"\n";
}
int main(){
// freopen("color2.in","r",stdin);
// freopen("color2.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--)solve();
return 0;
}
//1
//8
//3 5 2 5 1 2 1 4
upd 11.11
双十一真是个好日子。
貌似过了初中牲的 \(NOIP\) 线,可能要开 \(NOIP\) 游记了?
upd 11.19
蓝勾无缘了。事到如今还是好想哭。老师情报错了,去不了 NOIP 了……

浙公网安备 33010602011771号