2021 CSPJ

发布时间 2023-11-01 16:18:56作者: shirlybabyyy

 其实哪里需要模拟啊!!!这么简单的问题!!!是头猪也想得到

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;

int main()
{
	int n,l,r;
	cin>>n>>l>>r;
	if(l/n==r/n) cout<<r%n;
	else cout<<n-1<<endl;
	return 0;
}

  【21CSPJ普及组】插入排序(sort)

 其实也是直接模拟就可以,每次都记录一下改变之后每个数字的位置信息

#include <bits/stdc++.h>
using namespace std;
const int maxn=8005;

int t[maxn];
struct node{
	int pre,id;
}op[maxn];
int n,q;
bool cmp(node a,node b){
	if(a.pre!=b.pre) return a.pre<b.pre;
	else return a.id<b.id;
} 
int main()
{
	cin>>n>>q;
	for(int i=1;i<=n;i++) {
		cin>>op[i].pre;
		op[i].id=i;
	}	
	sort(op+1,op+1+n,cmp);
	//先记录排完序后每个点的位置
	for(int i=1;i<=n;i++){
		t[op[i].id]=i;
	} 
	while(q--){
		int opa,x,v;
		cin>>opa;
		if(opa==1){
			cin>>x>>v;
			op[t[x]].pre=v;
			//然后往两个方向扫描,因为不确定是变小了,还是变大了
			for(int j=n;j>=2;j--){
				if(cmp(op[j],op[j-1])) swap(op[j],op[j-1]);
			} 
			for(int j=2;j<=n;j++){
				if(cmp(op[j],op[j-1])) swap(op[j],op[j-1]);
			}
			//然后更新
			for(int i=1;i<=n;i++) t[op[i].id]=i;
		}
		else {
			cin>>x;
			cout<<t[x]<<endl;
		}
	}
	return 0;
}

  【21CSPJ普及组】网络连接(network)

1、就是字符串的处理,记住可以用sscanf(),sprintf()函数

int t=sscanf(s,"%d.%d.%d.%d:%d",&a,&b,&c,&d,&e);    t记录的是成功读取的个数,肯定要等于5,然后判断abcde的大小范围,然后判断是否合格,就是用abcde去构造一个字符串,判断与输入的是否一样即可。sprintf(s2,"%d.%d.%d.%d:%d",a,b,c,d,e);

2、判重直接用map<string,int>即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=8005;
map<string,int> vis;  //判重 
int n;
bool check(char s[]){
	int a=-1,b=-1,c=-1,d=-1,e=-1;
	int t=sscanf(s,"%d.%d.%d.%d:%d",&a,&b,&c,&d,&e);
	if(t!=5) return 0;
	if(a<0||a>255) return 0;
	if(b<0||b>255) return 0;
	if(c<0||c>255) return 0;
	if(d<0||d>255) return 0;
	if(e<0||e>65535) return 0;
	char s2[35];
	sprintf(s2,"%d.%d.%d.%d:%d",a,b,c,d,e);
	int len=strlen(s);
	for(int i=0;i<len;i++){
		if(s[i]!=s2[i]) return 0;
	}
	return 1;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		char op[105],ad[1005];
		cin>>op>>ad;
		if(op[0]=='S'){
			if(!check(ad)) cout<<"ERR"<<endl;
			else if(vis.count(ad)) cout<<"FAIL"<<endl;
			else {
				cout<<"OK"<<endl;vis[ad]=i;
			}
		}
		else{
			if(!check(ad)) cout<<"ERR"<<endl;
			else if(vis.count(ad)) cout<<vis[ad]<<endl;
			else cout<<"FAIL"<<endl;
		}
	}
	return 0;
}

  【21CSPJ普及组】小熊的果篮(fruit)

 这个其实基础算法,解决方法很多种,其实重点就是怎么处理“合并”的块,然后更新后重新去取数

1、首先对输入的数组先分块,输出每个块的第一个(记录哪个才是第一个),然后因为可能把一个块取完了,这里就直接continue,没取完就更新这个块里面那个才是第一。

2、每一轮取完了之后,要判断会不会有块能够结合,所以再创建一个队列,存放更新完的(合并后的),然后再次放到上面那个队列里面去

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
//很多种做法,直接写最好理解的队列,记住要维护每个队列的开始、结束位置,每次减少一个位置
//在每次出每个块的第一个元素的时候,记得两个块在队列里相邻且元素相同,就可以直接合并。
//-->两个队列
struct node{
	int st,ed,num;
};
bool vis[maxn];//判断有没有出队
int n,cnt;
int t[maxn]; //记录输入的数组 
queue<node> q,q2; 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
	}
	t[n+1]=!t[n];
	int si=1;
	for(int i=2;i<=n+1;i++){
		if(t[i]!=t[i-1]) {
			q.push((node){si,i-1,t[i-1]});
			si=i;
		}
	}
	cnt=n;
	//两个队列,一个先出去处理后放q2,然后又更新回q里 
	while(cnt){
		while(q.size()){
			node f=q.front();
			q.pop();
			while(vis[f.st]&&f.st<=f.ed) f.st++;
			if(f.st>f.ed) continue;
			printf("%d ",f.st); //
			vis[f.st]=1;
			cnt--;
			if(f.st==f.ed) continue;
			f.st++;
			q2.push(f); 
		}
		printf("\n");
		while(q2.size()){
			node f=q2.front();
			q2.pop();
			while(q2.size()){
				node nex=q2.front();
				if(f.num==nex.num){
					f.ed=nex.ed;
					q2.pop();
				}
				else break;
			}
			q.push(f); //丢回去,每次取完更新完之后又放回去 
		}
	}
	return 0;
}