window.cnblogsConfig = { homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

2023CSP复赛/NOIP备战模拟赛复盘集合

2023 10 03 CSP-J 模拟赛 复盘

这次模拟赛考的特别差,只有160。

T1:一上来,虽然不那么打卡,但也挺简单,然后五分钟写完,对了对样例,对了,走人。

T2:需要在O(nlogn)或者O(n)的时间复杂度求出每一个区间被覆盖的区间,这要怎么求啊?我想了半天也只知道O(n2)怎么做,然后发现一个小时过去了,同学们都貌似切掉了这一题,开始往后写了。感觉有点慌,普及T2没切出来……

T3:是挺水的,洪水填充+O(1)回答搞定。

T4:是一道大模拟+贪心,手动列举if的条件,列举了很多发现越来越多情况。于是就换了一种思路,写啊写,终于写完了100行。自己出了几个样例结果都成为了heck数据,有调了调,几个heck也过掉了。于是又出了十几个数据,貌似都对了。然后剩下时间十分钟,回去先把T2的暴力写完就没时间了。

最后成绩:

0+60+100+0

第一题竟然能暴0,这也是很奇怪的。发现是有个地方没有+1。

#include<bits/stdc++.h> using namespace std; string s; int m; int main(){ cin >> s; cin >> m; while(m--){ int a,b,c; cin >> a >> b >> c; a--,b--; c %= b-a+1; string e; for(int i=a;i <= b;i++){ e += s[(i-c) >= a? (i-c):b-abs((i-c)-a)+1]; } for(int i = a;i <= b;i++){ s[i] = e[i-a]; } }cout<<s<<endl; return 0; }

第二题其实我是几乎想到了正解,只是最后没有时间了,其实正解也不过就是sort排个序,动态求max即可。

#include<bits/stdc++.h> #define ll long long #define pii pair<int,int> #define fir first #define se second #define ull unsigned long long #define endl "\n" using namespace std; int n; const int N = 1e5+5; pii a[N]; int main(){ cin >> n; for(int i = 1;i <= n;i++){ cin >> a[i].fir >> a[i].se; } sort(a+1,a+1+n); int ans= 0; int maxr=0,maxn=0; for(int i = 1;i <= n;i++){ if(a[i].fir>a[i-1].fir){ maxr = max(maxn,maxr); } maxn = max(maxn,a[i].se); if(maxr > a[i].se) ans++; }cout<<ans; return 0; }

第三题过了也不意外,因为很水

#include <bits/stdc++.h> using namespace std; int n,m; const int N = 1005; char c[1005][1005]; int dx[4]={0,0,-1,1}; int dy[4]={1,-1,0,0}; int dis[N][N]; int val[N*N]; int res=0; int cnt=0; void dfs(int x,int y){ dis[x][y] = res;cnt++; for(int i = 0 ;i < 4;i++){ int xx=x + dx[i]; int yy=y + dy[i]; if(xx >= 1 && xx <= n && yy>=1&&yy<=m&&c[xx][yy]=='.'&&dis[xx][yy]==0){ dfs(xx,yy); } } } int main(){ cin >> n >> m; for(int i =1;i <= n;i++){ for(int j =1;j <= m;j++){ cin >> c[i][j]; if(c[i][j]=='*')dis[i][j] = -1; } } for(int i=1;i <= n;i++){ for(int j = 1;j <= m;j++){ if(!dis[i][j]){ cnt=0; ++res; dfs(i,j); val[res] = cnt; } } } for(int i = 1;i <= n;i++){ for(int j =1;j <= m;j++){ if(dis[i][j]!=-1)cout<<"."; else{ int ans=1; set<int> ve; for(int k=0;k<4;k++){ int xx=i+dx[k]; int yy=j+dy[k]; ve.insert(dis[xx][yy]); } for(auto it:ve){ ans+=val[it]; // cout<<val[it]<<endl; } cout<<ans%10; } }puts(""); } return 0; }

第四题我都傻了,竟然那么多个数据都没有heck掉。原来在只包含4和7的输入中有一组数据”7777“是有问题的,在判断包含4,7这个输入的时候没有考虑到越界+2的问题,然后还有一个地方应该else if和if颠倒才是对的,想起来还是太粗心了,要是这两个错没有,估计我就是机房唯一一个A的。虽然说在写复盘的时候还不能提交(因为代码源在比赛后一定时间不能提交)但是我拿着周思源的暴力60分代码跑了对拍,过掉了一千多个样例,甚至根袁梓熠的正解(挂成40)的代码对拍只有一个错误,而且这个错误明显是他错了。总结一下,这种多组数据的题目实在是太坑了,一个点错就挂掉。

总结:

这次考差的原因就是第二题没有想出来(正确来说其实是我审题不仔细,把”有多少个点被覆盖“看成”每个点覆盖的区间之和“,然而我还因为把题目看成后者,写了二分加sort等等,特别复杂。。)下次还是要审题仔细,不要图一时快。这次就是因为T2挂了,因此心态有些不好,有点慌张,导致后面都比较紧张,也是T4少了贪心情况的的一个原因。。。

不过这次下午的讲评还是非常高兴能够听到(全球第四, 2015IOI金牌,CF rating TOP 1,AT rating TOP 5)的大佬杜瑜皓老师的讲课,虽说是线上,但是感觉讲的很好!

2023 10 4 CSP-J模拟赛复盘

这次只考了200

T1:很简单,直接切了

T2:贪心嘛,直接开切,尽可能把最高位变得更大就可以了

T3:也是一个贪心,预处理树的深度和子树大小,然后sort一遍,关键字是深度-子树,也就是说每一个点如果变成黑色的话,其贡献是他到根节点的距离,然后还会影响他的子树的值,所以要减去子树大小。

T4:想了一下,像是个贪心?认为是一个DP+贪心+二分?然后细想,发现不知道如何logn求一个动态区间的最大值,别说,还想到单调队列 可这是pj组啊。最后没时间了,直接N^2暴力dp出来了。。

期盼得分100+100+100+60=360

最终得分90+20+30+60=200

挂分挂的惨啊。。

T1算约数的地方挂了。

#include <bits/stdc++.h> #define int long long using namespace std; void print(int x,int y){//约分并打印 int s=min(x,y); int flag=1; while(flag){ flag=0; for(int i =2;i <= __gcd(x,y);i++){ if(x%i==0 && y%i==0){ x/=i; y/=i; flag=1; } } } cout<<x<<"/"<<y<<endl; } signed main(){ int a,b,c,d; cin >> a >> b >> c >> d; if(a*d == c*b)cout<<"0/1"; else print(max(a*d,c*b)-min(a*d,c*b),max(a*d,c*b)); return 0; }

T2有一些没有特判,导致RE,没仔细想,n如果很大的话,可能处理出最大值还是有剩下的n,这一点没有特判掉,但是整体思路基本上是对的。

#include <bits/stdc++.h> using namespace std; char c[25]; int t; int n; bool check(){//判断是否已经是最大值了 for(int i=1;i<strlen(c);i++)if(c[i] >c[i-1]) return true; return false; } int main(){ cin >>t; while(t--){ scanf("%s",c); cin>>n; if(strlen(c)==1 || !check()) {//特判掉直接输出的情况 cout<<c<<endl; continue; } int j = 0; int f=n; while(n>0){ int maxn = c[j]-'0',maxi = j; for(int i=j;i <= min(j+n,(int)strlen(c)-1);i++){//找最大值 if(maxn<(c[i]-'0')){ maxn = c[i]-'0'; maxi = i; } } n-=maxi-j;//减去贡献 for(int i = maxi;i >= j+1;i--){ c[i]=c[i-1]; }c[j]=maxn+'0'; j++; if(!check())break;//如果已经是最大的,break } cout<<c<<endl; } return 0; }

T3我一开始想的是从叶子节点开始动态求max,也就是priority queue赛后找出了反例,不一定所有叶子都要取,反而直接把所有点的贡献sort一遍求前k大即可,然后因此AC。

#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2e5+5; int n,k; vector<int> mp[N]; int dep[N]; int son[N]; priority_queue<int> q; void dfs(int x,int fa){//深搜预处理深度和子树大小的数组。 son[x] = 1; for(auto it:mp[x]){ if(it==fa)continue; dep[it]=dep[x] + 1; dfs(it,x); son[x]+=son[it]; } } signed main(){ int ans=0; cin >> n >> k; for(int i = 1;i <= n-1;i++){ int u,v; cin >> u >> v; mp[u].push_back(v); mp[v].push_back(u); } dep[1]=0; dfs(1,0); for(int i = 1;i <= n;i++){//加入每一个点的贡献 q.push(dep[i]-son[i]+1); }for(int i =1;i <= k;i++)ans+=q.top(),q.pop();//计算答案 cout<<ans; return 0; }

T4:其实只需要映射一下,就可以变成最长下降子序列,因此可以用贪心二分来O(nlogn)解决掉。

#include<bits/stdc++.h> #define ll long long #define pii pair<int,int> #define fir first #define se second #define ull unsigned long long #define endl "\n" using namespace std; const int N = 1E6+10; int n; int dp[N]; int l[N],r[N]; bool cmp(int x,int y){return x>y;} int main(){ cin >> n; for(int i=1,x;i<=n;i++){ scanf("%d",&x); l[x]=i; }for(int i=1,x;i<=n;i++){ scanf("%d",&x); r[l[x]]=i; }int cnt=0; for(int i = 1;i <= n;i++){ int pos = lower_bound(dp+1,dp+1+cnt,r[i],cmp)-dp; dp[pos]=r[i]; cnt=max(cnt,pos); }cout<<cnt; return 0; }

总结,这次考的很差,我认为还是不够细心,贪心题一定要仔细细心想条件,不要漏掉了一些条件。还有就是时间安排不妥当,想玩玩对拍,结果T3对拍浪费很多时间,而且数据生成器写的有点问题,拍的也不是很理想。

10 05 CSP-J模拟赛

考的很差,只有180

目标100+100+100+0=300

实际100+60+10+10+180

T1:过了

#include <bits/stdc++.h> using namespace std; int x,k; int vis[4100]; int main(){ cin >> x >> k; for(int i = 1;i <= k;i++){ int op,x,y; cin >> op>>x; if(op==1){ cin >> y; vis[x]=1; vis[y]=1; }else{ vis[x]=1; } } int maxn = 0,minn = 0; for(int i = 1;i <= x-1;i++){ if(!vis[i]) maxn++; }for(int i = 1;i <= x-1;i++){ if(!vis[i] && !vis[i+1]){ i++;minn++; }else if(!vis[i]){ minn++; } }cout<<minn << " "<<maxn; return 0; }

T2:很容易想到两遍差分+前缀和,但是我是个傻子也不过分,开了long long 结果printf("%d"),改完后AC。

#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5+5; int n,m,k; int a[N]; struct node{ int l,r,d; }s[N]; int sao[N]; int qzh[N]; signed main(){ cin >>n >> m >>k; for(int i = 1;i <= n;i++){ scanf("%lld",&a[i]); }for(int i = 1;i <= m;i++){ scanf("%lld%lld%lld",&s[i].l,&s[i].r,&s[i].d); } for(int i = 1;i <= k;i++){ int x,y; scanf("%lld%lld",&x,&y); sao[x]++; sao[y+1]--; } for(int i=1;i<=m;i++){ sao[i]+=sao[i-1]; s[i].d *= sao[i]; // cout<<sao[i]<<" "; } for(int i = 1;i <= m;i++){ qzh[s[i].l] += s[i].d; qzh[s[i].r+1] -= s[i].d; } for(int i = 1;i <= n;i++){ qzh[i] += qzh[i-1]; } for(int i = 1;i <= n;i++){ printf("%lld ",qzh[i] + a[i]); }puts(""); return 0; } /* 记得开long long 扫描线思想: 维护x和y 计算出每一个操作需要进行多少次。 再乘上权值 再对l,r跑一遍前缀和。 */

T3:我把check里想复杂了,其实很简单可解决。

#include <bits/stdc++.h> using namespace std; int n, k; int a[10005]; bool check(double x){ double num1= 0, num2= 0; for (int i = 1; i <= n; i++){ if (a[i] >= x) num1 += a[i] - x; else num2 += x - a[i]; } return num1* (1 - k / 100.0) >= num2; } int main(){ cin >> n >> k; for (int i = 1; i <= n; i++){ cin >> a[i]; } double l = 0, r = 1000, mid = (l + r) / 2; while (r - l > 1e-9){ mid = (double)(l + r) / 2; if (check(mid)) { l = mid+1e-9; } else { r = mid; } } printf("%.9lf", l); return 0; }

T4:我原本想写贪心,结果没有想到贪心的思路,后面写了优先队列+dp,时间复杂度O(nlogn)完全可以过,然后比赛结束了还没有调出来,我以为样例没过是0分,所以交了一个-1的代码,最后发现原本的DP可以拿到40分(bei,痛失30分。。。

还有就是题意有点理解错了,我以为有有限个轮胎,原来只有一个,要是考场上知道这一点,特判+DP,还有50分。不过主要还是dp写错了,因为我去按照无限个轮胎来跑了,所以错了,整体思路也不对了。

正解:因为寒冷的情况必须用耐寒轮胎,所以如果寒冷时间>k,则输出-1。然后我们将耐寒设为0的段落,正常普通轮胎设成1的段落,贪心思路就是如果我们将1换成0,也就是说在普通时间用耐寒轮胎,可以省去2次换胎。当然sort一下,每一次选最短的段落,肯定是最优的,然后最后再特判一下最后结尾的情况就可以AC了。

#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 5; int n, k, t[N]; int main() { cin >> n >> k; int res= 0; for(int i = 1; i <= n; i++) { cin >> t[i]; if(t[i] < 0) res++; } if(res> k) { cout << "-1"; return 0; } k -= res; vector<int> ve; int ls= 2e9; for(int i = 1; i <= n; i++) { if(t[i] < 0) continue; int j = i; for(; j <= n && t[j] >= 0; j++); if(j <= n && i > 1) ve.push_back(j - i); else if(i > 1) ls= j - i; i = j; } int ans = 0; if(res> 0) ans = 2 * (ve.size() + 1); sort(ve.begin(), ve.end()); for(auto i : ve) { if(k >= i) { k -= i; ans -= 2; } } if(res > 0 && k >= n - ls - 1) { ans--; } cout << ans; return 0; }

总结:

这次又是因为不开long long 见祖宗,把题目想难了,挂分挂的很惨。

就是心态上有点紧张,前几次都是挂分挂的特别惨,所以这次前面几道题切的很快,就为了能够最后一题打出点东西来,结果最后一题题意理解错误,前面的也是细节挂掉,一举两失,下次还是要读题更加仔细,等到思考完在做,不然写完才发现思路错了,那就时间不够了,争取下一次不要挂分,要挂分也不要挂多于50,目标:350+!!!!!

2023 10 06 CSP-J模拟赛复盘

这次考的很差,只有200。主要原因因为T2爆零了。

目标得分:100+100+0+100

实际得分:100+0+0+100
T1:
AC签到题

#include <bits/stdc++.h> using namespace std; const int N = 105; int n,k; int a[N]; signed main(){ cin >> n >> k; int res=n; for(int i = 1;i <= n;i++){ scanf("%lld",&a[i]); if(a[i]==k)res--; } int cnt=0; while(res){ sort(a+1,a+1+n); for(int i = 1;i <= n;i++){ int j=i; for(;j <= n && a[i] == a[j];j++); j--; a[i]++; if(a[i]==k)res--; i=j; } ++cnt; }cout<<cnt; return 0; }

T2:
vector遍历写成只到<size-1,在两步跳着遍历的时候写成++。。

#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5+5; int n,k; int a[N]; bool cmp(int a,int b){ return a>b; } signed main(){ int t; cin >> t; while(t--){ cin>>n; vector<int> ji,ou; for(int i = 1;i <= n;i++){ scanf("%lld",&a[i]); if(a[i]&1){ ji.push_back(a[i]); }else{ ou.push_back(a[i]); } } sort(ji.begin(),ji.end(),cmp); int ans=0; for(auto it:ou){ if(it>0)ans+=it; } ans+=ji[0]; for(int i = 2;i < ji.size();i+=2){ if(ji[i]+ji[i-1] > 0){ ans+=ji[i]+ji[i-1]; } } cout<<ans<<"\n"; } return 0; }

T3:赛时没哟想出来

T4:想了一想,发现遍历n个点,然后再DFS,然后最后算出每一个点到达次数的组合数,时间复杂度O(nm),然后写完对拍之后,几万个数据都过掉了,最后也是AC了。

#include <bits/stdc++.h> #define int long long using namespace std; const int N = 3005; int n,m; vector<int> mp[N]; int vis[N]; int dp[N]; int dep[N]; void dfs(int x,int step){ if(step==2)return ; for(auto it:mp[x]){ if(vis[it])continue; // cout<<it<<' '<<step+1<<endl; dep[it]=max(dep[it],step+1); if(step+1==2)dp[it] ++; vis[it]=1; dfs(it,step+1); vis[it]=0; } } signed main(){ cin >> n >> m; for(int i =1;i <= m;i++){ int x,y; scanf("%lld%lld",&x,&y); mp[x].push_back(y); } // cout<<endl; int ans=0; for(int i = 1;i <= n;i++){ memset(dp,0,sizeof dp); memset(vis,0,sizeof vis); memset(dep,0,sizeof dep); dp[i]=0; vis[i]=1; dfs(i,0); for(int j =1;j <= n;j++){ if(dep[j]==2){ int res=1; // cout<<i<<" "<<j<<" "<<dp[j]<<endl; for(int k = dp[j];k > dp[j]-2;k--){ res*=k; }res/=2; ans+=res; } } } cout<<ans; return 0; }

我还怕这个时间复杂度过不去,开了火车头
。。

总结:

这次失分的原因,是因为T2不细心,遍历的地方写的太快了。下次还是先要把前两题稳拿了,别太赶着做后面两题。

2023.11.10测试 复盘

得分100+100+80,hhh

@2020luke 大佬290 %%%
T1:
怎么那么谁,红题-,好弱智。。
秒了/

#include <cstdio> #include <cstring> using namespace std; char s[103]; int main() { int _; scanf("%d", &_); while(_--) { scanf("%s", s + 1); int cntu = 0, cntl = 0, n = strlen(s + 1); for(int i = 1; i <= n; ++i) if('A' <= s[i] && s[i] <= 'Z') ++cntu; else if('a' <= s[i] && s[i] <= 'z') ++cntl; if(cntu > cntl) for(int i = 1; i <= n; ++i) if('a' <= s[i] && s[i] <= 'z') putchar(s[i] - 32); else putchar(s[i]); else for(int i = 1; i <= n; ++i) if('A' <= s[i] && s[i] <= 'Z') putchar(s[i] + 32); else putchar(s[i]); putchar('\n'); } return 0; }

T2:
也很水,看完题面一秒就会了,大概是红~橙。

#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5+5; int a[N],n; int sum; int qzh[N]; int hzh[N]; map<int,int> mp; signed main(){ // freopen("std.in","r",stdin); cin >> n; for(int i = 1;i <= n;i++)scanf("%lld",&a[i]); for(int i =1;i<=n;++i){ sum+=a[i]; qzh[i]=qzh[i-1]+a[i]; }for(int i = n ;i >= 1;i--){ hzh[i]=hzh[i+1]+a[i]; mp[hzh[i]]++; } int ans=0; mp[hzh[1]]--; for(int i =1;i<=n-2;i++){ mp[hzh[i+1]]--; if(qzh[i]*3==sum){ ans+=mp[qzh[i]]; } } cout<<ans; return 0; }

T3:
考试时也不知道是神经组织发什么神经,看错题了,看了半个小时,不是DP,就是假结论贪心,最后5分钟发现读错题目了,火速写暴力。。

正解:(其实也很水)。大概难度在橙。

#include <bits/stdc++.h> using namespace std; const int N = 1E5+5; int n,a[N]; pair<int,int> maxn1[N],minn1[N],maxn2[N],minn2[N]; int main(){ cin>>n; if(n<3){ cout<<0; return 0; } for(int i = 1;i <= n;i++)scanf("%d",&a[i]); for(int i = 0;i <= n+1;i++)minn1[i].first=minn2[i].first=1e9; for(int i = 0;i <= n+1;i++)maxn1[i].first=maxn2[i].first=-1e9; for(int i = 1;i <= n;i++){ if(maxn1[i-1].first<a[i])maxn1[i].first=a[i],maxn1[i].second=i; else maxn1[i]=maxn1[i-1]; if(minn1[i-1].first>a[i])minn1[i].first=a[i],minn1[i].second=i; else minn1[i]=minn1[i-1]; }for(int i = n;i >= 1;i--){ if(maxn2[i+1].first<a[i])maxn2[i].first=a[i],maxn2[i].second=i; else maxn2[i]=maxn2[i+1]; if(minn2[i+1].first>a[i])minn2[i].first=a[i],minn2[i].second=i; else minn2[i]=minn2[i+1]; } for(int i =1;i <= n;i++){ if(minn1[i-1].first < a[i] && a[i] > minn2[i+1].first){cout<<"3\n"<<minn1[i-1].second<<" "<<i<<" "<<minn2[i+1].second;return 0;} if(maxn1[i-1].first > a[i] && a[i] < maxn2[i+1].first){cout<<"3\n"<<maxn1[i-1].second<<" "<<i<<" "<<maxn2[i+1].second;return 0;} }cout<<0; return 0; }

总结:

其实很简单的题目,一个半小时也能没AK。主要还是读题不仔细,不够细心,下次一定要细心,认真。。

题目来源 AcWing


__EOF__

本文作者gsczl71
本文链接https://www.cnblogs.com/gsczl71/p/17854616.html
关于博主:GDSZ初一蒟蒻,明年拿下七级勾
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   gsczl71  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示