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 了……

posted @ 2025-10-14 21:11  Accept_Reality  阅读(14)  评论(0)    收藏  举报