CSP-J 2021 复赛游记

Day-1

啥也没干
晚上看了看洛谷的讨论,据说freopen在打开的最后要加

fclose(stdin);fclose(stdout);

不加也可。不过据说Linux在return 0之前不会自动关闭文件,在不确定的情况下,就先加上吧。

Day1

T1

8:30开考,8:40就做完第一题了,用的是暴力枚举。

#include<bits/stdc++.h>
using namespace std;
int n,l,r;
int ans=0;
int main(){
	freopen("candy.in","r",stdin);
	freopen("candy.out","w",stdout);
	scanf("%d%d%d",&n,&l,&r);
	for(int k=l;k<=r;k++){
		ans=max(ans,k%n);
	}
	cout<<ans<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

后来看题发现R-L可能大于10的9次方,也就是会超时。算了,先不管了,淦T2了。

T2

插入排序,一开始写了一个大概的代码框架,然后发现操作2是输出数字排序后的位置,于是直接推倒之前的框架重来,使用结构体存储数字原来的位置和数值,排序后就可以看见原来的位置了。
本来想用冒泡排序,然后发现冒泡太慢,直接用STL的快排。

#include<bits/stdc++.h>
#include<string.h> 
using namespace std;
struct NODE{
	int n;//数值 
	int rank;//编号 
};

int n,q;
const int MAX_N=8000+10;
struct NODE a[MAX_N],temp[MAX_N];

bool cmp(NODE A,NODE B){
	return A.n<B.n;
}

void sort(NODE* a,int n){//冒泡排序 
	for(int i=1;i<=n;i++){
		for(int j=1;j<i;j++){
			if(a[j].n>a[i].n)swap(a[i],a[j]);
		}
	}
}
int main(){
	freopen("sort.in","r",stdin);
	freopen("sort.out","w",stdout);
	scanf("%d%d",&n,&q); 
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i].n);a[i].rank=i;
	}
	while(q--){
		int op,x,v;
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d",&x,&v);
			a[x].n=v;
		}
		else if(op==2){
			scanf("%d",&x);
			memcpy(temp,a,sizeof(a));
			sort(temp+1,temp+n+1,cmp);
			//sort(temp,n);
			for(int i=1;i<=n;i++){
				if(temp[i].rank==x){//排序前的位置是rank 
					printf("%d\n",i);break;//排序后的位置是i 
				}
			}
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T3

一开始9:10左右淦完T2,然后专注的淦T3。T3题目很长,我决定分为两部分写,先写Server端再写Client端。
写了约15分钟还没写出成果,干脆先放在一遍,肝T4。

T4

还是一样,一开始没有思路,干到10:00左右,基本框架完成。

剩余的时间

10:00-10:30左右,首先是淦T1的另一种算法,因为T1用暴力循环R-L次可能超时,目测70分。
使用对拍大概的测了一下,发现我新写的算法不知道哪里出了问题,输出的数字都是错误的,可能连20分都不到,因此果断放弃,还是使用暴力算法。
(话说洛谷使用暴力算法,民间数据可以AC100分)
CSP-J 2021 复赛游记
T2也稍作修改,总体修改后代码如上所示,使用考场的样例试了一下,4个样例错了2个(还是1个,我不记得了)

然后专注的淦T3和T4。
T3硬模拟了出来,自以为没什么问题然而还是错误不断,考场的样例错了不少,而且样例输出特别长,根本找不到问题在哪里。
最终代码:

#include<bits/stdc++.h>
using namespace std;
struct NODE{
	string type;//表示Server或Client 
	int i;//服务器的编号 
	int a,b,c,d,e;
	bool fail;//连接是否失败 
	bool operator ==(struct NODE n){
		if(type==n.type && a==n.a && b==n.b && c==n.c && d==n.d && e==n.e)return true;
		return false;
	}
	bool connect(struct NODE n){
		if(type!=n.type && a==n.a && b==n.b && c==n.c && d==n.d && e==n.e)return true;
		return false;
	}
	bool legal(){
		if(a>=0 && a<=255 && b>=0 && b<=255 && c>=0 && c<=255 && d>=0 && d<=255 && e>=0 && e<=65536)return true;
		else return false;
	}
};
int n;
const int MAX_N=1010;
struct NODE net[MAX_N];
int main(){
	freopen("network.in","r",stdin);
	freopen("network.out","w",stdout);
	scanf("%d",&n);
	int temp=1;
	for(int i=0;i<n;i++){
		cin>>net[i].type;
		net[i].a=net[i].b=net[i].c=net[i].d=net[i].e=-1;
		scanf("%d.%d.%d.%d:%d",&net[i].a,&net[i].b,&net[i].c,&net[i].d,&net[i].e);
		if(net[i].legal()==false){
			cout<<"ERR"<<endl;continue;//忽略这条连接 
		}
		if(net[i].type=="Server")net[i].i=temp,temp+=1;
		if(net[i].type=="Server"){
			int flag=0;
			for(int j=0;j<i;j++){
				if(net[j]==net[i])flag=1;
			}
			if(flag==0)net[i].fail=false,cout<<"OK"<<endl;
			else net[i].fail=true,cout<<"FAIL"<<endl;
		}
		else if(net[i].type=="Client"){
			int flag=0;
			for(int j=0;j<i;j++){
				if(net[i].connect(net[j]) && net[i].fail==false){
					flag=1;
					cout<<net[j].i<<endl;
					break;
				}
			}
			if(!flag)cout<<"FAIL"<<endl;
		}
		//printf("%d.%d.%d.%d:%d",net[i].a,net[i].b,net[i].c,net[i].d,net[i].e);
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T4在11:20之前大概就干完了,中途还去了一次洗手间,就当是放松一下。(话说去洗手间就是放松的好机会)
思路大体是使用数组记录去掉的元素,然后就简略写了一下,然后发现第一个样例怎么都不对。

#include<bits/stdc++.h>
using namespace std;
int n;
const int MAX_N=2e5+10;
char a[MAX_N],rem[MAX_N],print[MAX_N];
bool check(){
	for(int i=0;i<n;i++){
		if(rem[i]==false)return false;
	}
	return true;
}
int main(){
	freopen("fruit.in","r",stdin);
	freopen("fruit.out","w",stdout);
	scanf("%d",&n);
	for(int i=0;i<n;i++)scanf("%d",&a[i]);
	for(;;){
		rem[0]=true;
		for(int i=1;i<n;i++){
			if(a[i]==-1)continue;//标记为已移除 
			if(a[i]!=a[i-1])rem[i]=true;//块的开头,需要移除 
			else rem[i]=false; 
		}
		for(int i=0;i<n;i++){
			if(rem[i] && !print[i])printf("%d ",i+1),print[i]=true;
		}
		printf("\n");
		for(int i=0;i<n;i++){
			if(rem[i])a[i]=-1;//标记为已移除 
		}
		if(check())break;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

最终发现题目有这句话:

注意,每次挑完一个果篮后,“块”可能会发生变化。比如两个苹果“块”之间的唯一桔子被挑走后,两个苹果“块”就变成了一个“块”。

然后针对这句话做了大量修改,然后发现代码越来越乱,测出来的还是错的,还错的更加离谱了,就干脆不加了,放弃了。
后来发现这题洛谷的民间数据只有10分,看来这还是很重要的一个点。

考试结束前30分钟都没事干,基本检查了一下freopen是否正确,文件夹是否有多余内容。我甚至发现旁边有人在玩谷歌浏览器的小恐龙游戏,估计是真的没事干了。
顺便在桌面写了个文件玩玩const和指针,因为实在没事干了。考场的环境甚至有python,然而我几乎不会

由于我座位号1号,于是第一个交文件走人。于是就这么结束了。
分数预估:
70+30+20+10=130,估计是要完蛋了。

上一篇:NOIP & csp 考前复习计划


下一篇:【CCF-CSP】画图