2022/7/14 cf训练(思维+构造+差分)

C. Helping the Nature
一道构造题。
难度:1700
题意:经过题目给定三种操作,1~i都减去1、i ~n都减去1、1 ~n都加上1,使得数组中所有值都为0,问最少需要多少次操作。
思路:乍一看觉得不难,但有几个点需要相通。
1.0 0 8 0 0需要24次操作,才能全部归0
2.若原始值中有负数,需要将其转化为非负数。
3.以0作为间隔来考虑最小次数。

只能想到这里,后面怎么处理就想不通了,看了dalao题解,几点提示:
1.看到对一段区间的操作,应马上想到一个工具----差分。创建一个差分数组b[N]
2.1~i都减去1---->b[1]-=1,b[i+1]+=1
3.i ~n都减去1—>b[i]-=1
4.1 ~n都加上1—>b[1]+=1

接下来分为两个步骤:
1.如果数组a中的值要全部相等,则b[1]=a[1],b[2~n]全部为0。操作2,3可对b[2 ~n]操作。
2.a数组中值如果全部为0,则在(1)的基础上b[1]必须为0。

代码:
顺利ac了,需要思考的东西很多,wa了一发,老问题没开longlong

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+6;
int n,a[N],b[N];
signed main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        b[1]=a[1];
        for(int i=2;i<=n;i++)
            b[i]=a[i]-a[i-1];
        int ans=0;
        for(int i=2;i<=n;i++)
        {
            if(b[i]>0)
                ans+=b[i],b[i]=0;
            else if(b[i]<0)
                b[1]+=b[i],ans-=b[i];
        }
        ans+=abs(b[1]);
        cout<<ans<<endl;
    }
    return 0;
}

B - Palindromic Numbers
这题根本就不是难度1100的构造题,起码1500+,做了好久,况且这个思路也不好想啊。
我的思路:如果第一个字符大于或者等于最后一个字符,则去构造111+这个进位数字;若是小于,则根据回文规则来构造一个数字(此处是我做复杂了,只需构造9999~这个类型数字即可)。思路有些地方错误了,具体看代码,对比ac代码和wr代码。

ac代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+6;
int n;
int ans[N];
signed main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n;
        string s;cin>>s;
        int g=s.length();
        for(int i=0;i<g;i++)
                ans[i]='9'-s[i];
        if(ans[0]!=0)
        {
            for(int i=0;i<g;i++)
                cout<<ans[i];
            cout<<endl;
        }
        else
        {
            for(int i=0;i<g;i++)
                ans[i]='9'-s[i];
            ans[0]=1;
            for(int i=1;i<g-1;i++)
                ans[i]++;
            ans[g-1]+=2;
            for(int i=g-1;i>=1;i--)
                if(ans[i]>=10)
            {
                ans[i]-=10;
                ans[i-1]++;
            }
            if(g==1)    ans[0]--;
            for(int i=0;i<g;i++)
                cout<<ans[i];
            cout<<endl;
        }
    }
    return 0;
}

wr代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+6;
int n;
char c[N];
int ans[N];
signed main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n;
        string s;cin>>s;
        int g=s.length();
        if(s[0]<s[g-1])
        {
            for(int i=0,j=g-1;i<=j;i++,j--)
            {
                if(i==j)
                {
                    c[i]='0';
                    continue;
                }
                if(s[i]<s[j])
                    c[i]=s[j]-s[i]+'0',c[j]='0';
                else if(s[i]==s[j])
                    c[i]=c[j]='0';
                else
                    c[i]='0',c[j]=c[i]-c[j]+'0';
            }
            for(int i=0;i<g;i++)
                cout<<c[i];
            cout<<endl;
        }
        else
        {
            for(int i=0;i<g;i++)
                ans[i]='9'-s[i];
            ans[0]=1;
            for(int i=1;i<g-1;i++)
                ans[i]++;
            ans[g-1]+=2;
            for(int i=g-1;i>=1;i--)
                if(ans[i]>=10)
            {
                ans[i]-=10;
                ans[i-1]++;
            }
            if(g==1)    ans[0]--;
            for(int i=0;i<g;i++)
                cout<<ans[i];
            cout<<endl;
        }
    }
    return 0;
}

D. Not a Cheap String
写了大概二十分钟,没有很专注地写,但也属实慢了一点,超时了一次,原因是memset的清零操作,这个以后能不用就不用了。
思路:一个贪心策略,如果一个字符串最小的字符都大于给定p值,则输出空字符;否则依次删除字符串中最大的字符,直到字符串的和小于等于p的值。
代码思路:使用结构体进行排序,然后标记被删除的字符串所在位置,常规操作。

#include<bits/stdc++.h>

using namespace std;
const int N=1e6+5;
struct node
{
    char s;
    int val,id;
}e[N];
bool vis[N];
bool cmp(node a1,node a2)   {return a1.val>a2.val;}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        string s;cin>>s;
        int p;cin>>p;
        char c;
        int mi=50,sum=0;
        for(int i=0;i<s.length();i++)
        {
            vis[i]=0;
            sum+=s[i]-'a'+1;
            if(mi>s[i]-'a'+1)
            {
                mi=s[i]-'a'+1;
                c=s[i];
            }
        }
        if(mi<=p)
        {
            for(int i=0;i<s.length();i++)
                e[i].s=s[i],e[i].id=i,e[i].val=s[i]-'a'+1;
            sort(e,e+s.length(),cmp);
            int g=0;
            while(sum>p)
            {
                sum-=e[g].val;
                vis[e[g].id]=1;
                g++;
            }
            for(int i=0;i<s.length();i++)
            {
                if(!vis[i])
                    cout<<s[i];
            }
            cout<<endl;
        }
        else
            cout<<""<<endl;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值