C++小白训练第五天

C++小白训练第五天

以下为牛客挑战

今日收获

存放相同的东西的序号时候可以用vector
vector<vector<int>>f(N);
这样就不会像二维数组一样被动

区间递归
变化不大的
f[i]=f[i-1]+{-1,1,0}

牛客周赛 Round 123

(34条未读私信) 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ

小红玩牌

A-小红玩牌_牛客周赛 Round 123

image-20260115131421472

解题代码

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];

signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n1,n2;
    string s1,s2;
    cin>>n1>>s1;
    cin>>n2>>s2;
    if(n1>n2){
        cout<<"Yes"<<endl;
    }else if(n1==n2){
        if(s1<s2){
            cout<<"Yes"<<endl;
        }else{
            cout<<"No"<<endl;
        }
    }else{
        cout<<"No"<<endl;
    }

	return 0;
}

小红作弊

B-小红作弊_牛客周赛 Round 123

image-20260115132145709

很简单只需要我们直接看看哪里多了的,多了的就是

解题代码

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];

signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    vector<array<int,2>>ans(14);
    int x1=0,x2;
    for(int i=1;i<=13;i++){
        cin>>ans[i][0];
    }
    for(int i=1;i<=13;i++){
        cin>>ans[i][1];
    }
    for(int i=1;i<=13;i++){
        int m=ans[i][0]+ans[i][1];

        if(m>4){
           x1+=m-4;
        }
        if(m<4){
            x2+=4-m;
        }
    }
    cout<<x1<<endl;

	return 0;
}

小红出对

C-小红出对_牛客周赛 Round 123

image-20260115135431658

5
1 A
1 B
3 A
2 A
3 B

输出

4
1 2
3 5

这个题目就是去掉重复的,然后记录下每一个种类的序号就行了

就是实现不好实现,但是我发现了我们可以用二维数组来存取一下

用vector存储

vector<vector<int>>f(N); 
if(!g[a][b]){
            g[a][b]=1;
            f[a].push_back(i);//相同的放在一个地方
    }

解题代码

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;


signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    vector<array<int,4>>g(N);
    vector<vector<int>>f(N);
    int n;
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++){
        int a;
        string s;
        cin>>a>>s;
        int b=s[0]-'A';
        if(!g[a][b]){
            g[a][b]=1;
            f[a].push_back(i);
        }
    }
    for(int i=1;i<N;i++){
        ans+=f[i].size()/2*2;//向下取整
    }
    cout<<ans<<endl;
    for(int i=1;i<N;i++){
        if(f[i].size()>=2){
            for(int j=0;j<f[i].size()-1;j+=2){
                cout<<f[i][j]<<" "<<f[i][j+1]<<endl;
            }
        }
    }

	return 0;
}

小红打牌

排列组合一下

D-小红打牌_牛客周赛 Round 123

image-20260115164413760

10
1 1 1 2 2 2 1 1 1 1
1

这个题思路就是,我们先统计一下全都的到底有出现的次数那些是大于1次的,那些是大于3次的个数。

然后去枚举数,确定s[i]那么s[i+1]也就确定,只要两个都大于等于3,我们就可以开始下一步了。

首先,我们先把自己在之前那部分的>1和>3的那部分剪掉。

再确定自己减完之后到底还有没有多余的了,有就加上作为最后两个对子的东西,nx是差不多还剩两个的了,只能自己提供一个的,然后ny,就是可以提供两组相同的数给我组成飞机

image-20260115165600325

实际就是找两对的组合,因为6张牌已经确定了。
里面的局部变量
nx:大于等于二的数量的,

ny:大于4的,就可以自己提供两个了

解题代码

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=998244353;
int a[N],b[N],c[N],pre[N];

signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    int ans=0;
    vector<int>s(N,0);
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        s[x]++;
    }
    int x=0,y=0;
    for(int i=1;i<N;i++){
        x+=(s[i]>1);
        y+=(s[i]>3);
    }

    for(int i=1;i<N-1;i++){
        if(s[i]>=3&&s[i+1]>=3){
            int nx=x,ny=y;
            //先把自己的那个先减去了,然后再加上到底自己的状态是多少。
            nx-=(s[i]>1)+(s[i+1]>1);
            ny-=(s[i]>3)+(s[i+1]>3);
            nx+=(s[i]-3>1)+(s[i+1]-3>1);
            ny+=(s[i]-3>3)+(s[i+1]-3>3);
            //Ny表示我自己就能提供两个,不需要你们给我提供了,nx是需要和别人一起组合才能成功,所以就排列组合
            ans=(ans+nx*(nx-1)/2+ny)%mod;
        }
    }
    cout<<ans<<endl;

	return 0;
}

小红出牌

区间递归

E-小红出牌(easy)_牛客周赛 Round 123

image-20260115210840001

5
5 3 1 2 4
1 2 3 2 1

暴力就是对新加入的直接进行排序加遍历就行了

正解要用到递归

image-20260115211133160

一共有3个可能,就是前面的f[i-1]--->f[i]变化的范围很小,只有-1,1,0;
所以我们就可以通过这个来做手脚。

我们可以用两个map数组L,R,来维护一段区间在边差那个,的权值,和区间右边差哪个的权值
第一种情况:
-1 相当于右边的R[x]>0且是存在缺少的,左边L[x]也是一样存在和大于零
我们就可以少1,并且把原来的减去就可以了。

1的话是没有,也没有大于0的,那就把这个数左右两边加加一下

0的话有两种一个是左边,一个是右边,分开讨论就行了
左的话就继续向[x-1]++;
右边的话就[x+1]++;
f[i]=f[i-1]+{-1,1,0}

暴力

开始想到的暴力的解法,只能过20%

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];

signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    vector<int>s(n);
    for(int i=0;i<n;i++){
        cin>>s[i];
    }
    for(int i=0;i<n;i++){
        vector<int>m;
        int count=0;
        for(int j=0;j<i+1;j++){
            m.push_back(s[j]);
        }
        sort(m.begin(),m.end());
//        for(int j=0;j<m.size();j++){
//            cout<<m[j]<<" ";
//        }
//        cout<<endl;
        if(m.size()==1){
            cout<<1<<" ";
            continue;
        }
        for(int k=0;k<m.size()-1;k++){

            if(m[k]+1!=m[k+1]){
                count++;
            }

        }

        cout<<++count<<" ";
    }

	return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];

signed main(){

	std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    map<int,int>L,R;
    int sum=0;//维护一个答案;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        int add=1;
        if(L.count(x)&&L[x]>0&&R.count(x)&&R[x]>0){
            L[x]--;
            R[x]--;
            add=-1;
        }else if(L.count(x)&&L[x]>0){
            L[x]--;
            L[x-1]++;
            add=0;
        }else if(R.count(x)&&R[x]>0){
            R[x]--;
            R[x+1]++;
            add=0;
        }else{
            //单前的左右两边一起维护一下
            R[x+1]++;
            L[x-1]++;
        }
        sum+=add;
        cout<<sum<<" ";
    }

	return 0;
}

image-20260115213549940

posted @ 2026-01-15 21:59  Godjian  阅读(3)  评论(0)    收藏  举报