牛客小白月赛22总结

牛客小白月赛22总结

前言:
本来觉得能进前一百的,但是,害…
B题如果做出来了,就肯定能进前一百了。感觉B应该不难,但是就是不知道怎么做,最终以四题告终(A、E、F、J)

看当时比赛的情况,感觉这四道题+B题都是非常简单的题,毕竟都AC都超过了一百。继续加油,题解出来认真补题!!!

先总结下自己做出来的四道题:

A:操作序列

题意:
无线长度的数列,初始状态都为0,有三种操作:

增加操作:给下标为 t 的数加 c 。特别注意,如果在下标 [t-30,t+30][t−30,t+30] 内有不为零的数,增加操作无效。(可以这样理解,要想该操作能进行,则必须这个范围的数都为0)
削减操作:让数列中下标最小的不为零数变为零。(如果全都为0,则输出skipped)
查询操作:查询数列中下标为 t 的数字是多少。

题解:
A真的搞我的心态,第一遍看题的时候没有注意到时间,觉得非常难,就直接没管,等到看了一会B的时候,再来看A,才发现时间限制居然是5s,起初想到的是map,毕竟map能自动排序嘛;写出来到写成功花了将近一个小时。。。。。结果一交TLE ,这心态瞬间崩了,然后继续看B,B仍然不会做,于是想着用结构体数组来模拟一下A,结果一交,居然过了。。。。

AC代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const double pi=3.14159;
const int maxn=1e6+5;
map<int,int>mp;
char s[10];
int n,pos,num;
struct node{
    int p,x;
};
node a[maxn+10];
int t;
bool cmp(node x,node y){
    return x.p>y.p;
}
int main(){
    scanf("%d",&n);
    getchar();
    t=0;
    while(n--){
        pos=0,num=0;
        gets(s);
        int len=strlen(s);
        int flag=0;
        int po;
        for(int i=0;i<len;i++){
            if(s[i]==' '){
                po=i;
                flag=1;
                break;
            }
        }
        if(s[0]=='-'){
            if(t==0){
                printf("skipped\n");
            }
            else{
                printf("%d\n",a[--t].x);
            }
        }
        else if(flag==0){
            int bit=1;
            for(int i=len-1;i>=0;i--){
                pos+=(s[i]-'0')*bit;
                bit*=10;
            }
            int Flag=0;
            for(int i=0;i<t;i++){
                if(a[i].p==pos){
                    printf("%d\n",a[i].x);
                    Flag=1;
                    break;
                }
            }
            if(Flag==0){
                printf("0\n");
            }
        }
        else{
            int bit=1;
            for(int i=po-1;i>=0;i--){
                pos+=(s[i]-'0')*bit;
                bit*=10;
            }
            bit=1;
            for(int i=len-1;i>po;i--){
                num+=(s[i]-'0')*bit;
                bit*=10;
            }
            int Flag=0;
            for(int i=0;i<t;i++){
                if(a[i].p>=(pos-30)&&a[i].p<=(pos+30)){
                    Flag=1;
                    break;
                }
            }
            if(Flag==0){
                a[t].p=pos;
                a[t].x=num;
                t++;
                sort(a,a+t,cmp);
            }
        }
    }
    return 0;
}

E:方块涂色

题意:
n*m的矩阵,初始状态都是没有涂色的,现在给定可以对r行,c列涂色;问最终剩余多少方块没有涂色

题解:
开始还觉得有点难,其实一想发现很简单

被涂上的方块数 num = rm+cn-(rc)
于是最终结果为:n
m-num

AC代码如下:

扫描二维码关注公众号,回复: 10333608 查看本文章
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=4e5+10;
ll n,m,r,c;
int main(){
    while(~scanf("%lld%lld%lld%lld",&n,&m,&r,&c)){
        ll num=n*m;
        ll num1=r*m+c*n-(r*c);
        cout<<num-num1<<endl;
    }
    return 0;
}

F:累乘数字

题意:
给定n,d;求n乘以100次d的结果

题解:
非常裸的大整数,只是我仍然不喜欢用C++写大数,还是用的Java

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main {
    public static void main(String args[]) {
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()) {
            BigInteger n=scan.nextBigInteger();
            int d=scan.nextInt();
            for(int i=1;i<=d;i++) {
                n=n.multiply(BigInteger.valueOf(100));
            }
            System.out.println(n);
        }
    }
}

J:计算A+B

题意:
每组给定一个字符串,然后需要判断是不是a+b的形式
(例如:+10、0+、01+001这些都不是a+b形式)
ps:可能出题人觉得前导0会没有那么水,在比赛中取消了前导0,但是我的代码仍然考虑了前导0,当时通知的时候已经敲完了QAQ。。。

如果不是a+b形式,输出skipped
如果是的话,输出结果

题解:
也是大整数、高精度相关问题。
只是会比上一题稍微复杂一点点,仍然用的Java

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main {
    public static void main(String args[]) {
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        for(int k=1;k<=n;k++) {
            String s=scan.next();
            char[] arr=s.toCharArray();
            int len=s.length();
            int pos=0;
            for(int i=0;i<len;i++) {
                if(arr[i]=='+') {
                    pos=i;
                    break;
                }
            }
             
            if(pos==0||pos==len-1) {
                System.out.println("skipped");
                continue;
            }
            if(arr[0]=='0'&&pos!=1) {
                System.out.println("skipped");
                continue;
            }
            if(arr[pos+1]=='0'&&(pos+1)!=len-1) {
                System.out.println("skipped");
                continue;
            }
             
            BigInteger a=BigInteger.ZERO;
            BigInteger b=BigInteger.ZERO;
            BigInteger bit=BigInteger.ONE;
             
            for(int i=pos-1;i>=0;i--) {
                a=a.add(BigInteger.valueOf(arr[i]-'0').multiply(bit));
                bit=bit.multiply(BigInteger.valueOf(10));
            }
             
            bit=BigInteger.ONE;
            for(int i=len-1;i>pos;i--) {
                b=b.add(BigInteger.valueOf(arr[i]-'0').multiply(bit));
                bit=bit.multiply(BigInteger.valueOf(10));
            }
             
            System.out.println(a.add(b));
        }
    }
}

补题部分…


B:树上子链

题意:
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。

题解:
好吧,我人傻了;居然是求树的直径,害,一道模板题

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
struct Edge{
    int to,nxt;
}edge[maxn*2];
int tot;
int head[maxn];
int vis[maxn];
ll dp[maxn];
int val[maxn];

ll ans;

void init(){
    tot=0;
    ans=-inf;
    memset(head,0,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(edge,0,sizeof(edge));
    memset(val,0,sizeof(val));
    memset(dp,0,sizeof(dp));
}
void add(int u,int v){
    tot++;
    edge[tot].to=v;
    edge[tot].nxt=head[u];
    head[u]=tot;
}
void dfs(int u,int pre){
    dp[u]=val[u];
    ans=max(ans,dp[u]);
    for(int i=head[u];i!=0;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==pre){
            continue;
        }
        dfs(v,u);
        ans=max(ans,dp[u]+dp[v]);
        dp[u]=max(dp[u],dp[v]+val[u]);
    }
}
int main(){
    init();
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&val[i]);
    }
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,-1);
    printf("%lld\n",ans);
    return 0;
}

C:交换游戏

题意:
一列上有12个孔,这12个孔中有些孔被遮挡住了。
假定我们用 ‘-’ 来表示没被遮挡住的孔,用 ‘o’ 来表示被遮挡住的孔。
如果相邻的三个孔有两个孔被遮挡,并且被遮挡的两个孔相邻,就是 ‘-oo’ 和 ‘oo-’。
对于这样的三个孔,我们可以将中间的孔的遮挡物移开,代价是将一端的遮挡物移到另一端没有被遮挡的孔上面。
对于一列给定的孔,你的任务是制定操作的顺序,使得最后剩余的被遮挡的孔的个数最少,并输出最后剩余的被遮挡的孔的个数。

题解:
居然直接暴力搜,害,马虎了

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
int n;
string s;
int ans;
void dfs(){
    for(int i=2;i<12;i++){
        if(s[i-2]=='-'&&s[i-1]=='o'&&s[i]=='o'){
            s[i-2]='o';
            s[i-1]='-';
            s[i]='-';
            dfs();
            s[i-2]='-';
            s[i-1]='o';
            s[i]='o';
        }
        if(s[i-2]=='o'&&s[i-1]=='o'&&s[i]=='-'){
            s[i-2]='-';
            s[i-1]='-';
            s[i]='o';
            dfs();
            s[i-2]='o';
            s[i-1]='o';
            s[i]='-';
        }
    }
    int num=0;
    for(int i=0;i<12;i++){
        if(s[i]=='o'){
            num++;
        }
    }
    ans=min(ans,num);
}
int main(){
    cin>>n;
    while(n--){
        ans=inf;
        cin>>s;
        dfs();
        cout<<ans<<endl;
    }
    return 0;
}

G:仓库选址

题意:
m*n的矩阵,在其中选择一点,使得其他点这个点的距离之和最小

题解:
这题其实很水啊,比赛的时候看都没看,可惜了
直接暴力枚举即可。。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
int t,n,m;
int mp[110][110];
int solve(int x,int y){
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==x&&j==y)
                continue;
            ans+=mp[i][j]*(abs(x-i)+abs(y-j));
        }
    }
    return ans;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&m,&n);
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&mp[i][j]);
            }
        }
        int ans=inf;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int num=solve(i,j);
                ans=min(ans,num);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

发布了139 篇原创文章 · 获赞 51 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/boliu147258/article/details/104451521