2021-09-04 校赛B 题解

     最近举办了一场校赛,但是因为老师忘记提醒我们了,所以这场比赛就变成了训练赛,让我们自己完成。比赛中我有了思路,因为做过和这类似的题目---最大连续子区间积 以及和这类问题。所以有了思路,应该是用dp来完成。但在比赛时间内我并没有完成,在赛后补题时才把它写完(还是太菜了)。
# 问题描述: 链接:https://ac.nowcoder.com/acm/contest/20033/B 来源:牛客网

给你一个长度为n的数组{1<=n<=10^5}1<=n<=10 5,每个元素值为{2^x}
或者{-2^x},(-100 < x < 100) ,(−100<x<100),你可以定义一个区间[L, R](1 <= L <= R <= n),然后把该数组在[L, R]区间内所有的元素累乘得到一个ans,求最大的ans(个位为{2^x},假如ans 为 1,那么输出{2^0} )

首先这一看就是字符输入的,为了处理数据,我们得把字符转成数字
代码如下(示例):

int n,a[100010],c[100010];
    string b[100010];
    cin>>n;
    for(int i=0;i<n;i++)
    {
       cin>>b[i];
        //cout<<b[i].size()<<endl;
    }
    for(int i=0;i<n;i++)
    {
    if(b[i][0]=='-')
    {
        c[i]=-1;
        if(b[i][3]=='-')
        {
            int x=0;
            for(int j=4;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=0;
            q[i].m=x;
        }
        else 
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=x;
            q[i].m=0;
        }
    }
    else 
    {
        c[i]=1;
        if(b[i][2]=='-')
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=0;
            q[i].m=x;
        }
        else 
        {
            int x=0;
            for(int j=2;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=x;
            q[i].m=0;
        }
    }
    }

后边就用类似最大连续子区间和以及积的想法来写。
类似于这样:
maxTmp = Math.max(a[i], Math.max(maxCur * a[i], minCur * a[i]));
minTmp = Math.min(a[i], Math.min(maxCur * a[i], minCur * a[i]));
maxCur = maxTmp;
minCur = minTmp;
result = Math.max(result, maxCur);
考试的时候我忘记了一步很关键的步骤,导致它一直wa了,一直dubug到4点终于想到了。
先贴一贴错误代码:
代码如下(示例):

#include<iostream>
using namespace std;
struct node
{
    int z,m;
}q[100010];
int main()
{
    int n,a[100010],c[100010];
    string b[100010];
    cin>>n;
    for(int i=0;i<n;i++)
    {
       cin>>b[i];
        //cout<<b[i].size()<<endl;
    }
    for(int i=0;i<n;i++)
    {
    if(b[i][0]=='-')
    {
        c[i]=-1;
        if(b[i][3]=='-')
        {
            int x=0;
            for(int j=4;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=0;
            q[i].m=x;
        }
        else
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=x;
            q[i].m=0;
        }
    }
    else
    {
        c[i]=1;
        if(b[i][2]=='-')
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=0;
            q[i].m=x;
        }
        else
        {
            int x=0;
            for(int j=2;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=x;
            q[i].m=0;
        }
    }
    }
    //cout<<q[0].m<<" "<<q[1].m<<" "<<q[2].m<<endl;
    int  res=-100000;
    int inf=10000000;
    int sum1=0,s1=c[0];
    int sum2=0,s2=c[0];
    //if(q[0].z-q[0].m)res=c[0]*(q[0].z-q[0].m+inf);
    /*else */
    res=sum1=sum2=c[0]*(q[0].z-q[0].m+inf);
    //cout<<res<<endl;
    for(int i=1;i<n;i++)
    {
        /*if(i==1)
        {
            cout<<s1<<s2<<endl;
            cout<<sum1<<sum2<<endl;
            cout<<q[0].z-q[0].m<<endl;
            cout<<max(c[i]*s1*(abs(sum1)+(q[0].z-q[0].m)),c[i]*s2*(abs(sum2)+(q[0].z-q[0].m)))<<endl;
        }*/
        sum1=max(max(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
        sum2=min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
        if(sum1>0)s1=1;
        else s1=-1;
        if(sum2>0)s2=1;
        else s2=-1;
        /*
            cout<<i<< " sum1:"<<sum1<<endl;
            cout<<i<< " sum2:"<<sum2<<endl;
            cout<<i<< "  res:"<<res<<endl;*/
        res=max(res,sum1);
    }
    //cout<<res<<endl;
    if(res==0)printf("2^0");
    else if(res<0)
    {
        int x;
        x=min(res%inf,inf-res%inf);
        printf("-2^%d",abs(res)-inf);
    }
    else
    {
        int x;
        x=min(res%inf,inf-res%inf);
        printf("2^%d",res-inf);
    }
    return 0;
}

后来想到了sum1会变,所以需要利用一个变量来存他之前的状态。
正确的代码:
代码如下(示例):

#include<iostream>
using namespace std;
struct node
{
    int z,m;
}q[100010];
int main()
{
    int n,a[100010],c[100010];
    string b[100010];
    cin>>n;
    for(int i=0;i<n;i++)
    {
       cin>>b[i];
        //cout<<b[i].size()<<endl;
    }
    for(int i=0;i<n;i++)
    {
    if(b[i][0]=='-')
    {
        c[i]=-1;
        if(b[i][3]=='-')
        {
            int x=0;
            for(int j=4;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=0;
            q[i].m=x;
        }
        else 
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            //if(x%2==0)c[i]=1;
            q[i].z=x;
            q[i].m=0;
        }
    }
    else 
    {
        c[i]=1;
        if(b[i][2]=='-')
        {
            int x=0;
            for(int j=3;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=0;
            q[i].m=x;
        }
        else 
        {
            int x=0;
            for(int j=2;j<b[i].size();j++)
            {
                x=x*10+(b[i][j]-'0');
            }
            q[i].z=x;
            q[i].m=0;
        }
    }
    }
    //cout<<q[0].m<<" "<<q[1].m<<" "<<q[2].m<<endl;
    int  res=-100000;
    int inf=10000000;
    int sum1=0,s1=c[0],sumt;
    int sum2=0,s2=c[0];
    //if(q[0].z-q[0].m)res=c[0]*(q[0].z-q[0].m+inf);
    /*else */
    sumt=res=sum1=sum2=c[0]*(q[0].z-q[0].m+inf);
    //cout<<res<<endl;
    for(int i=1;i<n;i++)
    {
        /*if(i==1)
        {
            cout<<s1<<s2<<endl;
            cout<<sum1<<sum2<<endl;
            cout<<q[i].z-q[i].m<<endl;
            cout<<min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m)))<<endl;
            cout<<c[i]*(q[i].z-q[i].m+inf)<<endl;
            cout<<min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf))<<endl;
        }*/
        sum1=max(max(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
        //cout<<min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf))<<endl;
        sum2=min(min(c[i]*s1*(abs(sumt)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
        //if(i==1)cout<<sum2<<" "<<endl;
        if(sum1>0)s1=1;
        else s1=-1;
        if(sum2>0)s2=1;
        else s2=-1;
        res=max(res,sum1);
        /*
            cout<<i<< " sum1:"<<sum1<<endl;
            cout<<i<< " sum2:"<<sum2<<endl;
            cout<<i<< "  res:"<<res<<endl;*/
        sumt=sum1;
    }
    //cout<<res<<endl;
    if(res==0)printf("2^0");
    else if(res<0)
    {
        int x;
        x=min(res%inf,inf-res%inf);
        printf("-2^%d",abs(res)-inf);
    }
    else
    {
        int x;
        x=min(res%inf,inf-res%inf);
        printf("2^%d",res-inf);
    }
    return 0;
}
总结:有时候想到思路了,感觉思路无比正确,但还是会出现一些错误导致题目ac不了。如何快速地找出这些错误我还得练习,说实话在比赛的时候真的气死了,写了好久,还是一直wa。气的我一直搞到了凌晨2点还是写不出(而且因为一些原因寝室没有空调,真的很烦躁)。直到我在地上躺了一会儿 ,冷静了下来,开始找例子来hack我的代码,终于在四点钟ac了。果然扣代码的时候还是需要一个冷静的头脑,不能急,越急越写不出来。(最终原因果然还是因为我太菜了 ┭┮﹏┭┮)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,CSP-J2021复赛有两道题目,分别是分糖果和小熊的果篮。 对于第一题分糖果,题目来源是CCF,难度为入门。根据给出的代码,这是一个基于循环的算法,通过遍历[l,r]区间内的数,计算数对n取模后的最大值。具体的实现细节可以参考引用中的代码。这道题目属于入门级别,比较简单。 第二题是关于小熊的果篮。给定一个长度为n的数组a,其中连续的相同元素被视为一个块,要求按照块的顺序输出每个块的头元素,并删除已输出的元素。具体的实现细节可以参考引用中的代码。这道题目需要使用双链表来处理,时间复杂度为O(n)。 综上所述,CSP-J2021复赛的题目包括分糖果和小熊的果篮,具体的解题思路和代码实现可以参考上述引用内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [[CSP-J 2021]比赛题解](https://blog.csdn.net/weixin_56550385/article/details/126811201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [新鲜出炉的 CSP-J 2021 复赛题目 题解](https://blog.csdn.net/qq_23109971/article/details/121024436)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值