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训练(思维+构造+差分)的主要内容,如果未能解决你的问题,请参考以下文章
CF 990D Graph And Its Complement 第十八 构造思维
CF989C A Mist of Florescence 构造 思维好题 第八题
Codeforces Round #619 (Div. 2)/CF1301 思维+贪心+模拟+构造+二维ST表