当前位置:   article > 正文

2023河南ccpc省赛总结(附带部分题题解)_小水獭游河南

小水獭游河南

前言:本人大一萌新,第一次打ccpc线下赛,和队友A3题,收获铜牌一枚,感受到了老师所说的氛围感。因为F题滑动窗口优化不会写(坤础忘了),痛失银牌,来年再战。

题目链接:Dashboard - 2023 CCPC Henan Provincial Collegiate Programming Contest - Codeforces (Unofficial mirror by Menci)

题目:Problem A. 小水獭游河南(签到)

小水獭来到河南旅游,它认为一个字符串 s 是 HENAN 的当且仅当存在两个非空字符串 a 和 b 满
足如下三个条件:
• a 由小写字母组成,且 a 中每种字母只出现了一次。
• b 由小写字母组成,且 b 是回文串,也就是说将 b 翻转后得到的字符串和 b 相同。
• 将 a 和 b 顺序拼接得到的字符串和 s 相同,也就是说 s = a + b。
例如 henan 是 HENAN 的,因为 henan=he+nan,此外也可分解为 hena+n。但 hhnan 和 ysmihoyocom
不是 HENAN 的。
现在给定一个字符串,请你帮助小水獭判断它是不是 HENAN 的。

这题只需要我们暴力枚举即可,最多只用枚举到下标为25的地方(下标从0开始),因为往后必定会出现a中有重复字符的情况(英文字母就26个啊),不满足题目条件。所以只需要枚举前min(len,26)位,用substr函数截取子串,reverse翻转子串判断是否为回文串即可。

注意:这题有个坑点是len的长度为1,这样就不满足题目要求a,b都为非空的情况,直接输出NaN即可。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <queue>
  5. #include <cstring>
  6. #include <algorithm>
  7. #include <map>
  8. #include <string>
  9. #include <set>
  10. #include <unordered_map>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef pair<int,int> pii;
  14. int cnt[26];
  15. void solve(){
  16. memset(cnt,0,sizeof cnt);
  17. string s;cin>>s;
  18. int len=s.size();
  19. if(len==1){
  20. cout<<"NaN\n";
  21. return;
  22. }
  23. for(int i=0;i<min(len,26);i++){
  24. if(cnt[s[i]-'a']){
  25. cout<<"NaN\n";
  26. return;
  27. }
  28. cnt[s[i]-'a']++;
  29. string s1,s2=s.substr(i+1);
  30. s1=s2;
  31. reverse(s2.begin(),s2.end());
  32. if(s1==s2){
  33. cout<<"HE\n";
  34. return ;
  35. }
  36. }
  37. cout<<"NaN\n";
  38. return;
  39. }
  40. int main() {
  41. int T=1;cin>>T;
  42. while(T--)solve();
  43. return 0;
  44. }

 题目:Problem H. Travel Begins(贪心)

 这题应该是个贪心,让我们将n分成至多份,然后求每份和的最大值和最小值。

根据题上的要求,求最小时,我们把n每次分出来0.4999999...求最大时,把n每次分出来0.5。

求最小时分两种情况:1.n能分出来k个0.49999.... 2.n分不出来k个0.49999...

同理,求最大也是这个思路,观察能不能k个分出来0.5

注意:我这个方法计算时会出现浮点数,所以前面强制转了int类型。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <queue>
  5. #include <cstring>
  6. #include <algorithm>
  7. #include <map>
  8. #include <string>
  9. #include <set>
  10. #include <unordered_map>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef pair<int,int> pii;
  14. void solve(){
  15. int n,k;cin>>n>>k;
  16. //算最小值部分
  17. if(n-(k-1)*0.5<=0){
  18. cout<<0;
  19. }
  20. else {
  21. if((k-1)&1){
  22. cout<<(int)(n-(k-1)*0.5+1);
  23. }
  24. else cout<<(int)(n-(k-1)*0.5);
  25. }
  26. cout<<" ";
  27. //算最大值部分
  28. if(n-k*0.5>0){
  29. if((k-1)&1){
  30. cout<<(int)(k-1+n-(k-1)*0.5)+1;
  31. }
  32. else cout<<(int)(k-1+n-(k-1)*0.5);
  33. }
  34. else {
  35. cout<<n*2;
  36. }
  37. cout<<"\n";
  38. }
  39. int main() {
  40. int T=1;cin>>T;
  41. while(T--)solve();
  42. return 0;
  43. }

题目:Problem F. Art for Last(滑动窗口)


这题的思路是,从头开始枚举每一个长度为k的区间。在这个区间内找到一个最小的差值,然后计算(最小的差值*区间两端点的差值),最后取个min即可。证明就不写了,因为是随便选k个数,排序后直接取就行。

这题用的是滑动窗口优化写的,不然的话时间每次查找最小值时会有很多重复操作,时间复杂度是O(n^{2}) ,1e6的范围直接爆掉。

赛后补题用优先队列实现滑动窗口,再算上排序。时间复杂度是O(n\log n),过掉。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <queue>
  5. #include <cstring>
  6. #include <algorithm>
  7. #include <map>
  8. #include <string>
  9. #include <set>
  10. #include <unordered_map>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef pair<int,int> pii;
  14. const int N=5e5+10;
  15. int a[N],q[N],b[N],c[N];
  16. int n,k;
  17. int main() {
  18. cin>>n>>k;
  19. for(int i=1;i<=n;i++)scanf("%d",&a[i]);//输入原数组
  20. sort(a+1,a+1+n);//排序
  21. for(int i=1;i<n;i++){
  22. b[i]=a[i+1]-a[i];//计算两数差值
  23. }
  24. /* for(int i=1;i<n;i++)cout<<b[i]<<" ";
  25. cout<<endl; */
  26. priority_queue<pii,vector<pii>,greater<pii> > q;
  27. //优先队列实现滑动窗口
  28. for(int i=1;i<k;i++)q.push({b[i],i});
  29. //存储差值和下标,以插值排序。我这里先存储了k个。
  30. for(int i=1;i+k-1<=n;i++){
  31. //枚举区间算最大
  32. c[i]=q.top().first;
  33. while(q.top().second<=i&&q.size())q.pop();
  34. //下标不满足时直接删除。等同于滑动窗口的去除队头操作
  35. q.push({b[i+k-1],i+k-1});
  36. //直接将差值和下标加入即可,优先队列会自动排序。
  37. }
  38. /* for(int i=1;i<n;i++)cout<<c[i]<<" ";
  39. cout<<endl; */
  40. ll res= 1e18;//小心不开long long
  41. for(int i=1;i+k-1<=n;i++){
  42. res=min(1LL*(a[i+k-1]-a[i])*c[i],res);//计算最小值
  43. }
  44. cout<<res;
  45. return 0;
  46. }

题目:Problem C. Toxel 与随机数生成器(确实挺随机的)

题解里说解法很多,确实!

我们截取前1000个字符,然后从1001开始找,如果有相同那就是NO;否则就YES

  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <queue>
  5. #include <cstring>
  6. #include <algorithm>
  7. #include <map>
  8. #include <string>
  9. #include <set>
  10. #include <unordered_map>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef pair<int,int> pii;
  14. int main() {
  15. string s,s1;cin>>s;
  16. s1=s.substr(0,1000);
  17. s.erase(0,1000);
  18. if(s.find(s1)!=-1)cout<<"NO\n";
  19. else
  20. cout<<"YES\n";
  21. return 0;
  22. }

结尾:

大一萌新第一次参加线下比赛,能拿奖牌十分甚至九分激动。

F题的滑动窗口优化卡了很久也没能调出来,痛失银牌,很可惜(基础差了)。卡太久就应该换题了,第一次参加没有经验。团队合作是很重要的一点,找队友思维的漏洞,三个人如果自己写自己的,那只能打铁。

前几题都是思维题,并没有涉及太多算法,所以要注重对思维的训练。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/443362
推荐阅读
相关标签
  

闽ICP备14008679号