今天这场打的不是很好,能出的题目没有全出。都是一些思路上的问题。
第一道开的题是I题 :最长回文串长度
第一眼看上去很难,是个回文问题,但是题目不要求顺序,那就很容易了,哈希存值,偶数个全加上,奇数个减一加上,同时标记一下,因为回文串中心可以有单独的一个字符。代码如下:
#include<bits/stdc++.h>
using namespace std;
char s[10005];
int a[30],b[30];
int main(){
while(scanf("%s",s)!=EOF){
int len=strlen(s);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<len;i++){
if(s[i]>='a'&&s[i]<='z'){
a[s[i]-'a']++;
}else{
b[s[i]-'A']++;
}
}
bool flag=false;
int sum=0;
for(int i=0;i<26;i++){
if(a[i]&1){
sum+=a[i]-1;
flag=true;
}else{
sum+=a[i];
}
if(b[i]&1){
sum+=b[i]-1;
flag=true;
}else{
sum+=b[i];
}
}
if(flag)sum++;
printf("%d\n",sum);
}
return 0;
}
下一道是G题,之前做过类似的题目,刚开始写反了符号没搓出样例,就试着交了一发bfs,果然炸内存了。然后重新写,因为奇数只能加,偶数才能除2,所以还是很好写的。代码如下:
#include<bits/stdc++.h>
using namespace std;
int a,b;
int main(){
while(scanf("%d %d",&a,&b)!=EOF){
if(a>b){
printf("%d\n",a-b);
}else{
int sum=0;
while(b>a){
if(b&1){
b++;
}else{
b/=2;
}
sum++;
}
sum+=abs(a-b);
printf("%d\n",sum);
}
}
return 0;
}
然后是c题,简单的结构体快排题,没什么坑,只要根据条件把不要的数据过滤掉就行。
#include<bits/stdc++.h>
using namespace std;
struct node{
int id,w,e,r,g;
friend bool operator < (const node &a,const node &b){
if(a.w!=b.w)return a.w>b.w;
return a.id>b.id;
}
}k[10005],now;
int ans;
int main(){
int n,a,b,c;
while(scanf("%d %d %d %d",&n,&a,&b,&c)!=EOF){
ans=0;
for(int i=0;i<n;i++){
scanf("%d %d %d %d %d",&now.id,&now.w,&now.e,&now.r,&now.g);
if((a==1&&now.e==0)||(now.r>b)||(now.g>c)){
}else{
k[ans++]=now;
}
}
sort(k,k+ans);
for(int i=0;i<ans;i++){
printf("%d %d %d %d %d\n",k[i].id,k[i].w,k[i].e,k[i].r,k[i].g);
}
}
return 0;
}
然后翻到了h题,看题面就知道是线段树,单点更新加减只要update正负数就行,不是很难,一道模板题。代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAXN 50005
struct node{
int l,r;
ll sum;
}k[MAXN<<2];
inline void build(int l,int r,int x){
k[x].l=l;
k[x].r=r;
if(l==r){
scanf("%lld",&k[x].sum);
return;
}
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
k[x].sum=k[x<<1].sum+k[x<<1|1].sum;
}
inline void update(int root,int val,int x){
if(k[x].l==k[x].r){
k[x].sum+=val;
return;
}
int mid=(k[x].l+k[x].r)>>1;
if(root<=mid)update(root,val,x<<1);
if(root>mid)update(root,val,x<<1|1);
k[x].sum=k[x<<1].sum+k[x<<1|1].sum;
}
inline ll query(int l,int r,int x){
if(l<=k[x].l&&r>=k[x].r){
return k[x].sum;
}
int mid=(k[x].l+k[x].r)>>1;
ll sum=0;
if(l<=mid)sum+=query(l,r,x<<1);
if(r>mid)sum+=query(l,r,x<<1|1);
return sum;
}
int main(){
int t,ans=1;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
build(1,n,1);
char s[6];
printf("Case %d:\n",ans++);
while(scanf("%s",s)){
if(s[0]=='E')break;
if(s[0]=='A'){
int a,b;
scanf("%d %d",&a,&b);
update(a,b,1);
}else if(s[0]=='S'){
int a,b;
scanf("%d %d",&a,&b);
update(a,-b,1);
}else{
int a,b;
scanf("%d %d",&a,&b);
printf("%lld\n",query(a,b,1));
}
}
}
return 0;
}
这题看到就觉得会卡掉dfs,然后就没去写,后面看榜单过了不少人,然后仔细想了想,其实也不难。
题解:题解链接
之后是本来就写好了的k题,一直找不出坑点。
直到后面想到因为地面是字符,采取的方法是map映射,所以可以能导致起点和终点相同的情况下没有输出0;加了一行代码救过了;
#include<bits/stdc++.h>
using namespace std;
#define inf 1000005
#define N 255
int val[N][N];
int dist[N],vis[N];
unordered_map<string,int>num;
int n,s,e,ans;
inline int minnnn(int a,int b){
return a>b?b:a;
}
inline void dijkstra(){
for(int i=0;i<ans;i++){
dist[i]=val[s][i];
vis[i]=0;
}
dist[s]=0;
vis[s]=1;
for(int i=1;i<ans;i++){
int minn=inf;
int a=-1;
for(int j=0;j<ans;j++){
if(!vis[j]&&minn>dist[j]){
minn=dist[j];
a=j;
}
}
if(a==-1)return;
vis[a]=1;
for(int j=0;j<ans;j++){
if(!vis[j]&&val[a][j]!=inf){
if(dist[j]>dist[a]+val[a][j]){
dist[j]=dist[a]+val[a][j];
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
while(cin>>n){
if(n==-1)break;
string start,end;
num.clear();
cin>>start>>end;
num[start]=s=0;
num[end]=e=1;
ans=2;
for(int i=0;i<155;i++){
for(int j=0;j<155;j++){
if(i!=j)val[i][j]=inf;
else val[i][j]=0;
}
}
for(int i=0;i<n;i++){
string a,b;
int c;
cin>>a>>b>>c;
int aa,bb;
if(num.find(a)==num.end()){
num[a]=aa=ans++;
}else{
aa=num[a];
}
if(num.find(b)==num.end()){
num[b]=bb=ans++;
}else{
bb=num[b];
}
val[aa][bb]=val[bb][aa]=minnnn(c,val[aa][bb]);
}
dijkstra();
if(start==end)dist[1]=0;
cout<<(dist[1]==inf?-1:dist[1])<<endl;
}
return 0;
}
最后出的一道题是B题,这题刚开始是自己画图推的,所以推错了,怎么都想不明白,最后写了一发dfs,求出:2 8 16 28 44,发现每次递增的数都会加4.然后就很简单了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m[100005];
int main(){
m[1]=2;
m[2]=8;
ll sum=8;
for(int i=3;i<=100000;i++){
m[i]=m[i-1]+sum;
sum+=4;
}
int n;
while(scanf("%d",&n)!=EOF){
printf("%lld\n",m[n]);
}
return 0;
}
赛后补题,E题:
题解链接:点击跳转
D题:
题解:https://blog.csdn.net/weixin_43823753/article/details/104524638
J题:
题解:https://blog.csdn.net/weixin_43823753/article/details/104524863
总结:还是太菜了,很多题目想复杂了,本来J题也不难,刚开始看错题目了导致后面没有去想这道题,导致了没有出。
之后再把题目补完。之后的训练也不能放松,好好利用时间提高自己的水平。