2023CSP-J复赛冲刺模拟赛四赛后补题报告

目录

一.比赛概况:

二.比赛过程:

三.题解报告

         【T1:复读机】

1.    题意: 

2.   数据范围:                        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​ 

3.    赛时本题做题想法/题解:

4.    AC代码:

         【T2:小可的矛与盾】

1.    题意:

2.    数据范围:

3.    赛时本题做题想法:

4.    题解:

5.    AC代码:

          【T3:不合法字符串】

1.    题意: 

2.    数据范围:

3.    赛时本题做题想法:

4.    题解:

5.    AC代码:

       【T4:虚假的珂朵莉树】

1.    题意: 

2.    数据范围:

3.    赛时本题做题想法:

4.    题解:

5.    AC代码:

四.赛后总结:


一.比赛概况:

        比赛共4题,250/400,T1~T4:100/90/20/40

        T2没考虑左端点,-10,气死我了。

        T3思路有了,和老师讲的一样,我却只把它放在暴力里(一个if,分开了我与AC)

二.比赛过程:

        T1是一道简单的字符串操作的题,秒了。

        T2是一道是一道模拟,但数据过大,要前缀和优化,秒了。

        (T1+T2才用了20min,导致被T3T4虐了2h+)

        T3又是一道字符串的题(今天捅字符串老窝了???),像是一个字典树(J组有字典树?),但写不出来,只能暴力。

        T4是一道图论(J组有珂朵莉树???)。只能暴力。

        (今天的暴力竟然都拿到了,题比前两天简单了)

三.题解报告:

                                         【T1:复读机】

                                                                 (100分)

1.    题意: 

        给定一个长度为n的仅包含小写字母和数字的字符串,字母表示需要复读的消息,数字表示要复读的次数。这个字符串中可能包含多个数字, 当多次出现数字时,如a5b2,从左到右解析,a5表示将a复读5遍,原字符串变为aaaaab,遇到数字 2 ,再全部复读 2 遍,即aaaaabaaaaab 。  

2.   数据范围:

        30%的数据下:所有数字独立出现,即数字最多只有一位。

        100%的数据下:1\leqslant t\leqslant 100,最终的字符串长度\leqslant 5*10^5

3.    赛时本题做题想法/题解:

        直接模拟,p来存之前的字符串,sp来存新的字符串,把新串字母加到sp中,数字存到x中,最后把x个sp赋值到p上。

4.    AC代码:

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int t,n;
string a;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		cin>>a;
		string p="";
		for(int i=0;i<a.size();){
			string sp=p;
			while(a[i]>='a'&&a[i]<='z') sp=sp+a[i++];
			int x=0;
			while(a[i]>='0'&&a[i]<='9') x=x*10+(a[i++]-'0');
			p=sp;
			for(int j=2;j<=x;j++) p+=sp;
		}
		cout<<p<<endl;
	}
	return 0;
}

                                    【T2:小可的矛与盾】

                                                           (90分,已补题)

1.    题意:

        有n个人站成一排(1到n),每人都有一个战斗力x​i​​=i,有的当矛,有的当盾,矛的攻击力和盾的防御力和本身的战斗力相同。将他们分成两个阵营,[1,pos]为第一阵营,只考虑矛的攻击力总和w;[pos+1,n]为第二阵营,只考虑盾的防御力总和v.求对于所有的0\leqslant pos\leqslant n+1\left | w-v \right |的值最小,求\left | w-v \right |最小为多少。

2.    数据范围:

        20%的数据下:n\leqslant 10

        40%的数据下:n\leqslant 10^3

        100%的数据下:n\leqslant 10^5

3.    赛时本题做题想法:

       是一道模拟题,枚举1-n+1,把v和w算出来,取最小值。但数据过大,要前缀和优化。

4.    题解:

        因为0\leqslant pos\leqslant n+1,所以枚举1-n+1,因为n\leqslant 10^5,所以用前缀和优化。

5.    AC代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
int n;
string s;
long long m[100005],d[100005],ans=1e18;
int main(){
	cin>>n;
	cin>>s;
	s=" "+s;
	for(int i=1;i<s.size();i++){
		m[i]=m[i-1];
		d[i]=d[i-1];
		if(s[i]=='0') m[i]+=i;
		if(s[i]=='1') d[i]+=i;
	}
	for(int i=0;i<=n;i++){//考试是i=1,落了一个左端点,-10
		long long w=m[i],v=d[n]-d[i];
		long long p=(w>v)?(w-v):(v-w);
		ans=min(ans,p);
	}
	cout<<ans;
	return 0;
}

                                      【T3:不合法字符串】

                                                                (20分,已补题)

1.    题意: 

       给出若干个不合法的字符串s[i],和一篇小说str ,需要把str中的不合法字符串用 *和谐掉。当用最少的 * 和谐字符串,输出和谐之后的小说。

2.    数据范围:

        20%的数据下:n=1

        50%的数据下:小说长度\leqslant 1500

        100%的数据下:1\leqslant t\leqslant 100,1\leqslant n\leqslant 10,每个不合法字符串长度\leqslant 10,小说长度\leqslant 10^5

3.    赛时本题做题想法:

        没思路,看暴力,应该是删不合法字符串的最后一位,写上了。

4.    题解:

        对于输入的字符串来说,和谐最后的字符价值远比其他位置要大。(所以当时的思路对了,把外面的if去了就行了。)所以枚举str,再枚举s[i],对字符串每一位往前寻找,若是找到任意一个以这一位结尾的单词就删最后一位。

5.    AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
int t,n,p=0;
string a,s[15];
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++) cin>>s[i];
		cin>>a;
		for(int i=0;i<a.size();i++){
			for(int j=1;j<=n;j++){
				if(i<s[j].size()-1) continue;
				if(a.substr(i-s[j].size()+1,s[j].size())==s[j]) a[i]='*'; 
			}
		}
		cout<<a<<endl;
	}
	return 0;
}

                                   【T4:虚假的珂朵莉树】

                                                                (40分,已补题)

1.    题意: 

        有一颗n个节点的树,根节点为1,有点权。设每个节点与根节点距离是这个节点的深度。小可会在这棵树上增加m条虚假边,无重边(增加的虚假边不影响节点深度)。之后小可会进行 q 次操作:1:让结点u的权值增加k,与结点 u 相邻的深度比结点 u 小的结点中重复操作1。2:让结点u的权值增加k,与结点u相邻的深度比结点 u 大的结点中重复操作2。求经过q次操作之后,所有的节点的权值是多少。(由于权值可能很大,请将权值对10^9+7进行取模。)

2.    数据范围:

        20%的数据下:1\leqslant n\leqslant 10^3,m=0,q\leqslant 10^3,k\leqslant 10^3

        另有20%的数据下:1\leqslant n\leqslant 10^5,m=0,且只有操作2 。

        100%的数据下:1\leqslant n\leqslant 10^5,1\leqslant m\leqslant 2*10^5,1\leqslant q\leqslant 2*10^5,k\leqslant 10^9

3.    赛时本题做题想法:

        又到图论了,我又兴奋了。看题,可以模拟,就按模拟来写。

        又发现,可以改进。把每一次的结果存起来,到最后再进行模拟。

        在考试时,我只能想到这。但这就是优化的极限吗?

4.    题解:

        不!

        我们已经把结果都存起来,但模拟太耗时间。我们可以分类讨论。

        对于1,只能从下往上,所以我们把深度排序。按从下到上进行操作,只需要一边就行。

        对于2,同理,从上到下。

5.    AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define mod 1000000007
#define N 1000005
#define mp make_pair
#define f first
#define s second
using namespace std;
int n,m,q,deep[N],V[N],fst[N],nxt[N],idx=0;
long long a[N],wup[N],wdown[N];
vector<pair<int,int> > ve;
void add(int a,int b){
	V[idx]=b;
	nxt[idx]=fst[a];
	fst[a]=idx++;
}
void dfs(int u,int fa){
	ve.push_back(mp(deep[u],u));
	for(int i=fst[u];i!=-1;i=nxt[i]){
		int v=V[i];
		if(v==fa) continue;
		deep[v]=deep[u]+1;
		dfs(v,u);
	}
}
int main(){
	memset(fst,-1,sizeof(fst));
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	dfs(1,1);
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	while(q--){
		int t,u;
		long long k;
		scanf("%d%d%lld",&t,&u,&k);
		if(t==1) wup[u]=(wup[u]+k)%mod;
		else wdown[u]=(wdown[u]+k)%mod;
	}
	sort(ve.begin(),ve.end());
	for(int i=0;i<ve.size();i++){
		int x=ve[i].s;
		for(int j=fst[x];j!=-1;j=nxt[j]){
			int y=V[j];
			if(deep[y]>deep[x])	wdown[y]=(wdown[y]+wdown[x])%mod;
		}
	}
	reverse(ve.begin(),ve.end());
	for(int i=0;i<ve.size();i++){
		int x=ve[i].s;
		for(int j=fst[x];j!=-1;j=nxt[j]){
			int y=V[j];
			if(deep[y]<deep[x]) wup[y]=(wup[y]+wup[x])%mod;
		}
	}
	for(int i=1;i<=n;i++) printf("%lld ",(a[i]+wdown[i]+wup[i])%mod);
	return 0;
}

四.赛后总结:

        今天是目前分最高的一天,但还是有一些失误的点。1.没把数据看全(T2) 2.不够自信(T3) 3.把思路伸下去(T4)

        (听说明天题更简单)

                                                日期:2023年10月04日星期三
                                                              姓名:董峻熙

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSP-J复赛历年试题pdf是指CSP-J的复赛历年试题的PDF文件。CSP-J是中国计算机学会(CCF)主办的一项高中生计算机科学与编程的竞赛。复赛CSP-J竞赛的第二个阶段,参赛者需要通过初赛选拔才能进入复赛CSP-J复赛历年试题pdf中包含了以往CSP-J复赛的试题和答案。这些试题主要涵盖了计算机科学与编程的各个方面,包括编程语言、算法、数据结构、计算机网络等。参赛者可以通过研究历年试题,了解CSP-J竞赛的题型和出题风格,提高自己的解题能力和编程水平。 CSP-J复赛历年试题pdf对于参赛者来说具有很大的参考价值。通过研究这些试题,参赛者可以了解到高水平的计算机科学与编程问题是如何被设计和解决的。同时,参赛者还可以通过尝试解答这些试题,检验自己的知识和技能,发现自己的不足之处并进行改进。 此外,CSP-J复赛历年试题pdf还对教师和学生进行教学和学习有很大的帮助。教师可以利用这些试题作为教学资源,丰富教学内容和方法,提高学生的计算机科学与编程能力。学生可以通过研究这些试题,扩展知识面,提升解决问题和编程的能力。 总之,CSP-J复赛历年试题pdf是一份重要的学习和竞赛资料,对参赛者、教师和学生都具有很大的参考和帮助作用。通过研究这些试题,大家可以更好地了解计算机科学与编程的相关知识和技能,并提升自己的竞赛和学习能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值