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

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    



以上是关于2022/7/14 cf训练(思维+构造+差分)的主要内容,如果未能解决你的问题,请参考以下文章

CF980B Marlin 构造 思维 二十四

CF 990D Graph And Its Complement 第十八 构造思维

CF989C A Mist of Florescence 构造 思维好题 第八题

Codeforces Round #619 (Div. 2)/CF1301 思维+贪心+模拟+构造+二维ST表

CF1364D Ehab‘s Last Corollary(思维,环,二分图,构造)

CF1364D Ehab‘s Last Corollary(思维,环,二分图,构造)