bistuacm 2019年第⑧场新生训练赛题解
比赛链接:
http://citel.bjtu.edu.cn/vjudge/contest/view.action?cid=328#overview
比赛难度:cf 1000~1500
A
知识点:字符串
题意:寻找所有单词中大写字母最多的大写字母数量。
解法:单词按空格隔开,所以可以直接scanf读取,自动按空格分割字符串。
#include<bits/stdc++.h> using namespace std; int main(){ int m=0,n; cin>>n; char s[11111]; while(scanf("%s",s)!=-1){ int i,sum=0; for(i=0;s[i]!='\0';i++)sum+=(s[i]>='A'&&s[i]<='Z'); m=max(m,sum); } cout<<m; }
B
知识点:枚举
题意:用尽可能少的问号替代第一个字符串的字符,使其成为第二个字符串的子串(问号可代表任意字符)。
解法:由于n只有1000,因此O(n^2)暴力枚举即可。求出最长公共子串。注意需要记录该子串的位置方便统计问号的位置。
#include<bits/stdc++.h> using namespace std; int main(){ int m,n,i,dy=0,j; char a[1111],b[1111]; cin>>m>>n>>a>>b; int ma=0; for(i=0;i<n-m+1;i++){ int sum=0; for(j=0;j<m;j++)sum+=a[j]==b[i+j]; if(sum>ma){ ma=sum; dy=i; } } cout<<m-ma<<endl; j=dy; for(i=0;i<m;i++)if(a[i]!=b[i+j])cout<<i+1<<" "; }
C
知识点:区间合并/前缀和
题意:数组中每个数a[i]代表对从第i-1个位置往前a[i]个位置染色。问最终未染色数量
解法:即每次对区间:(i-a[i],i-1)染色(若a[i]>i则是对(0,i-1)染色)。在数组上染色问题可以用前缀和解决:区间(x,y)染色即令s[x]++,s[y+1]–。然后最后求一次前缀和,前缀和结果为0的项即代表没被染色的位置。
#include<bits/stdc++.h> using namespace std; int a[1111111]; long long sum[1111111]={0}; int main(){ int n,i; cin>>n; for(i=0;i<n;i++)scanf("%d",&a[i]); for(i=0;i<n;i++){ sum[i]--; if(a[i]>=i)sum[0]++; else sum[i-a[i]]++; } long long s=0; for(i=1;i<n;i++)sum[i]+=sum[i-1]; int cnt=0; for(i=0;i<n;i++)cnt+=!sum[i]; cout<<cnt; }
D
知识点:图论/dfs
题意:给定一有根树。每次操作选择一个点,和一个颜色,可对该点以及其子树上所有点染成这个颜色。问所有点染色成指定颜色的最小操作数。
解法:显然只要有相邻边目的颜色不同,就需要进行一次额外染色。因此dfs求最终相邻边不同数字的对数即可。
#include<bits/stdc++.h> using namespace std; vector<int>g[111111]; int sum=1; int a[111111]; int visited[111111]={0}; void dfs(int x){ visited[x]=1; int i; for(i=0;i<g[x].size();i++){ if(!visited[g[x][i]]){ sum+=a[x]!=a[g[x][i]]; dfs(g[x][i]); } } } int main(){ int i,n; cin>>n; for(i=2;i<=n;i++){ int x; cin>>x; g[x].push_back(i); g[i].push_back(x); } for(i=1;i<=n;i++)cin>>a[i]; dfs(1); cout<<sum; }
E
知识点:贪心/字符串
题意:定义两个字母差的绝对值为两个字母的距离。两个字符串的距离为每个字符的距离之和。给定一字符串和一个数字k,求任意一个字符串,使其到给定字符串的距离为k。
解法:先求出可能的距离最大值max(am的字母选择z,nz的字母选择a的情况)。若k>max显然无解。当k≤max时,从前往后遍历字符串,优先选择最大值的情况来消耗k,当k被消耗得当前不需要最大值的情况改变当前字符。之后所有的字符保持原状即可。
#include<bits/stdc++.h> using namespace std; int main(){ int temp[26]; int n,k,i; cin>>n>>k; char a[111111]; cin>>a; for(i=0;i<13;i++)temp[i]=25-i; for(i=13;i<26;i++)temp[i]=i; int sum=0; for(i=0;i<n;i++)sum+=temp[a[i]-'a']; if(k>sum)cout<<-1; else{ for(i=0;i<n;i++){ if(k){ if(k>=temp[a[i]-'a']){ if(a[i]>='n')cout<<'a'; else cout<<'z'; k-=temp[a[i]-'a']; } else{ if(a[i]>='n')cout<<(char)(a[i]-k); else cout<<(char)(a[i]+k); k=0; } } else cout<<a[i]; } } }
F
知识点:图论/bfs
题意:对一棵树进行染色,需保证相邻两边的3个点颜色不同。求最少的颜色种类,并输出一种染色方案。
解法:对整棵树进行bfs,需要记录每个点的上一个点是哪个点,从某点v搜索到下一个点时,需要满足该点和点v、点v所有子节点、以及点v上一个点的颜色都不同的前提下,从1开始往上染色。
#include<bits/stdc++.h> using namespace std; vector<int>g[200011]; int c[200001]={0}; int visited[200001]={0}; int m=1; void bfs(){ int i; queue<int>q; q.push(1); visited[1]=1; c[1]=1; while(!q.empty()){ int temp=q.front(),k=1; for(i=0;i<g[temp].size();i++){ if(!visited[g[temp][i]]){ visited[g[temp][i]]=temp; while(k==c[temp]||k==c[visited[temp]])k++; c[g[temp][i]]=k; m=max(m,k); k++; q.push(g[temp][i]); } } q.pop(); } } int main(){ int n,i; cin>>n; for(i=0;i<n-1;i++){ int x,y; cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } bfs(); cout<<m<<endl; for(i=1;i<=n;i++)cout<<c[i]<<" "; }
- 2018年新生个人训练赛第十二场
- 新生训练赛round2--G. Maya Calendar(模拟)
- ACdream HUT新生摸底训练赛 B - 娜娜梦游仙境系列——跳远女王 bfs
- 2018年新生个人训练赛第十场(第29-30届宁波市信息学竞赛小学组)
- 北邮新生训练赛3解题报告
- 北邮还是新生吗训练赛12
- ACdream HUT新生摸底训练赛 C 娜娜梦游仙境系列——吃不完的糖果 DP
- 北邮新生训练赛3解题报告
- 北邮还是新生吗训练赛12
- ACdream HUT新生摸底训练赛 D - 娜娜梦游仙境系列——村民的怪癖 KMP
- ACdream HUT新生摸底训练赛 E - 娜娜梦游仙境系列——莫名其妙的插曲 数论
- ACM2016级新生第三周训练赛
- ACM2016级新生第三周训练赛
- 2018-2019赛季多校联合新生训练赛第四场
- Hut 新生训练赛第二场 迟来的解题报告
- Contest1353 - 2018年新生个人训练赛第十七场.问题. A: 珠心算测验
- ACdreamXMUT新生摸底训练赛C - 娜娜梦游仙境系列——吃不完的糖果
- 2018年新生个人训练赛第十一场(第27届宁波市信息学竞赛小学组,初中组)
- bzoj 4819: [Sdoi2017]新生舞会
- 顺序表——数据结构实验课源代码,菜鸡的第一篇博客,大一新生,代码参考课本严蔚敏 吴伟民——数据结构(C语言版)