美文网首页
牛客寒假算法基础训练营day-1

牛客寒假算法基础训练营day-1

作者: _NewMoon | 来源:发表于2020-04-30 00:28 被阅读0次

    写在前面:寒假之前报名了牛客的寒假算法训练营,当时没有好好参加,主要还是自己太菜,正好临近五一,所以计划每天学习一下当时比赛时候的题目和相关算法,因为这次训练营的题目是针对竞赛的,所以很多知识点我都还没学过,所以这里只记录一下相对来说简单一点的题目,后续学习了相关知识点后会持续补充~

    官方题解地址:https://ac.nowcoder.com/discuss/364600?type=101&order=0&pos=1&page=3&channel=-1

    A. honoka和格点三角形

    因为是格点三角形且面积为1,所以只存在两种形式的三角形:底为2高为1的和底为1和高为2的,题目还要求三角形至少有一条边是与坐标轴平行的,所以我们再分为两条边都平行和只有一条边平行这两类进行讨论:
    贴张我自己的笔记:


    note

    代码:

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    typedef long long LL;
    
    const int mod = 1e9+7;
    LL n,m;
    int main()
    {
        LL ans = 0;
        cin>>n>>m;
        
        //两边平行
        ans = 4 * ((n-1)*(m-2)%mod + (n-2)*(m-1)%mod)%mod;
        
        //底边与x轴平行
        ans = (ans + 2 *(n-1)*(m-2)%mod*(m-2) + 2*(m-1)*(n-2)%mod*(n-2)%mod)%mod;
        
        //底边与y轴平行
        ans = (ans + 2 * (m-1)*(n-2)%mod*(m-2)%mod + 2*(n-1)*(m-2)%mod*(n-2)%mod)%mod;
        
        cout<<ans<<endl;
        return 0;
    }
    

    G.eli和字符串

    对每个字母都预处理一个数组,然后用尺取法(双指针)对26个数组依次进行扫描,更新答案

    代码:

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <unordered_map>
    
    using namespace std;
    
    const int N = 200100;
    string s;
    int n,k;
    int a[30][N];
    
    int main()
    {
        cin>>n>>k;
        cin>>s;
        s = " " + s;
        
        //预处理
        for(int i = 0; i<26; i++){
            for(int j = 1; j<=n; j++)
                if(s[j] == ('a' + i))
                    a[i][j] = 1;
        }
     
        int ans = 1e9;
        for(int i = 0; i<26; i++){
            int res = N,l = 1,r = 1,sum = 0;
            while(1){
                while(r<=n && sum<k) sum += a[i][r++];
                if(sum < k) break;
                res = min(res,r-l);
                sum -= a[i][l++];
            }
            //cout<<res<<endl;
            ans = min(ans,res);
        }
        if(ans == N) cout<<-1<<endl;
        else cout<<ans<<endl;
        
        return 0;
    }
    

    H.nozomi和字符串

    也是用尺取法,找到满足条件的最大区间

    代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    string s;
    int n,k;
    
    //尺取法
    int solve(char a,char b){
        int l = 0, r = 0,cnt = 0,res = 1;
        
        for(int i = 0; i<n; i++){
            if(s[i] == a){
                if(cnt <k){
                    cnt++;
                    r++;
                }
                else{
                    while(l<=r && s[l] != a) l++;
                    l++,r++;
                }
            }
            else r++;
            res = max(res,r-l);
        }
        return res;
    }
    int main()
    {
        cin>>n>>k>>s;
        int ans = max(solve('0','1'),solve('1','0'));
        cout<<ans<<endl;
        return 0;
    }
    

    I.nico和niconiconi

    DP问题,dp[i]表示前i个字符的最大得分,状态转移方程为:
    if(s.substr(i - 3, 4) == "nico")then dp[i] = max(dp[i],dp[i - 4] + a)
    if(s.substr(i - 5, 6) == "niconi")then dp[i] = max(dp[i],dp[i- 6] + b)
    if(s.substr(i - 9,10) == "niconiconi")then dp[i] = max(dp[i], dp[i - 10]+ c)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    
    using namespace std;
    
    const int N = 300010;
    int a,b,c;
    int n;
    long long dp[N];
    string s;
    
    int main()
    {
        cin>>n>>a>>b>>c>>s;
        s = " " + s;
        long long ans = 0;
        if(n>=4){
            for(int i = 1; i<=n; i++){
                dp[i] = dp[i-1];
                if(i>=4)
                    if(s.substr(i-3,4) == "nico") 
                        dp[i] = max(dp[i-4] + a,dp[i]);
                if(i>=6){
                    if(s.substr(i-5,6) == "niconi")
                        dp[i] = max(dp[i-6] + b,dp[i]);
                }
                if(i>=10){
                    if(s.substr(i-9,10) == "niconiconi")
                        dp[i] = max(dp[i-10] + c,dp[i]);
                }
                
            }
            ans = dp[n];
        }
        //for(int i = 1; i<=n; i++) cout<<dp[i]<<endl;
        cout<<ans<<endl;
        return 0;
    }
    

    至此,day-1还有一个图论题,一个数论题,后面再更新~
    2020 4.30 凌晨0.27分,顶不住了,溜了。

    相关文章

      网友评论

          本文标题:牛客寒假算法基础训练营day-1

          本文链接:https://www.haomeiwen.com/subject/haoowhtx.html