Codeforces Round #780 (Div. 3)(ABCDEF1F2)
Posted 斗奋力努
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #780 (Div. 3)(ABCDEF1F2)相关的知识,希望对你有一定的参考价值。
Codeforces Round #780 (Div. 3)(ABCDEF1F2)
A. Vasya and Coins
题意:
有a个1元硬币和b个2元硬币,问不能组成的最小价格是多少
思路:
没有1元硬币肯定就是1,有的话就是a+2*b+1。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,a,b;
void solve()
scanf("%d%d",&a,&b);
if(a==0) puts("1");
else printf("%d\\n",a+2*b+1);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
B. Vlad and Candies
题意:
长度为n的序列,每次让当前序列的最大值的元素减1,如果最大值元素个数有多个,可以任意选其中一个减1,问是否可以在不对同一个位置元素进行减1操作的情况下,将全部元素都减为0
思路:
对于最初的最大值,最大值-次大值<=1肯定就是好的,因为有个伴,可以来回减,所以输出
"
Y
E
S
"
"YES"
"YES";否则输出
"
N
O
"
"NO"
"NO"
注意特判掉只有一个元素的情况,只有一个元素那么其必须为1才能是
"
Y
E
S
"
"YES"
"YES"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,q,a[N];
void solve()
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
if(n==1)
if(a[1]==1) puts("YES");
else puts("NO");
return;
sort(a+1,a+n+1);
if(a[n]-a[n-1]>=2) puts("NO");
else puts("YES");
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
C. Get an Even String
题意:
有一个字符串,问最少删除多少个字符,保证剩下字符组成的新字符,满足对于任意
i
%
2
=
=
1
i\\%2==1
i%2==1,有
s
[
i
]
=
s
[
i
+
1
]
s[i]=s[i+1]
s[i]=s[i+1]
思路:
对于每种字符,我们记录其上一次出现的位置,然后讨论是否使其保留就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,dp[N];
char s[N];
map<char,int>pos;
void solve()
pos.clear();
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)
dp[i]=dp[i-1];
if(pos[s[i]]) dp[i]=max(dp[i],dp[pos[s[i]]-1]+2);
pos[s[i]]=i;
printf("%d\\n",len-dp[len]);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
D. Maximum Product Strikes Back
题意:
有一个由
−
2
,
−
1
,
0
,
1
,
2
\\-2,-1,0,1,2\\
−2,−1,0,1,2五种元素构成的长度为n的序列,问序列前面删除多少个元素和后面删除多少个元素,使得剩下的元素的乘积最大,如果没有元素剩余,此时默认值为1
思路:
我们知道没有元素剩余时值为1,那么初始最大值为1。实际上最大值也要改为使用了多少个2
我们在序列的最前面和最后面各添加一个元素0(加边界),随后我们讨论所有相邻的两个0直接的情况,因为取了元素0,那么值就会为0,这样肯定会小于最大值。
对于相邻两个0之间的数,因为乘积足够,我们可以采用记录其中绝对值为2的个数就行了,同时记录其中负数的个数。
如果负数的个数为偶数,那么我们直接拿该段全部去和最大值比较。
如果负数的个数为奇数,那么需要分来两种情况
情况1: 只有一个负数的情况
序列 : [0][2,1,2,-1,2,1][0]
我们分成前后两部分: [2,1,2]----([-1])----[2,1]
情况2: 有多个个负数的情况
序列 : [0][2,1,2,-1,2,2,-2,1,-2,1,2,1][0]
我们分成前中后两部分: [2,1,2]----([-1])----[2,2,-2,1]----([-2])----[1,2,1]
不过我们发现,因为总的是奇数个负数。
我们选择前+([-1])+中可以得到一个正数,构成此时的新前端
我们选择中+([-2])+后可以得到一个正数,构成此时的新后端
再去和最大值比较
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,q,a[N],pre[N],fu[N];
vector<int>pos0;
void solve()
pos0.clear();
pos0.push_back(0); //加边界
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
if(a[i]==0) pos0.push_back(i);
if(abs(a[i])==2) pre[i]=pre[i-1]+1;
else pre[i]=pre[i-1];
if(a[i]<0) fu[i]=fu[i-1]+1;
else fu[i]=fu[i-1];
pos0.push_back(n+1); a[n+1]=0; //加边界
int mx2=0,ansl=n,ansr=0;
int len=pos0.size();
for(int i=1;i<len;i++)
int l=pos0[i-1]+1,r=pos0[i]-1;
if(l>r) continue;
int numfu=fu[r]-fu[l-1];
int num2=pre[r]-pre[l-1];
if(numfu%2==0)
if(num2>mx2)
mx2=num2;
ansl=l-1;
ansr=n-r;
else
int idx1=-1,idx2;
for(int j=l;j<=r;j++)
if(a[j]<0)
if(idx1==-1) idx1=j;
idx2=j;
if(idx1==idx2)
int qian2=pre[idx1-1]-pre[l-1];
int hou2=pre[r]-pre[idx1];
if(qian2>=hou2&&qian2>mx2)
mx2=qian2;
ansl=l-1;
ansr=n-idx1+1;
else if(hou2>=qian2&&hou2>mx2)
mx2=hou2;
ansl=idx1;
ansr=n-r;
else
int qian2=pre[idx2-1]-pre[l-1];
int hou2=pre[r]-pre[idx1];
if(qian2>=hou2&&qian2>mx2)
mx2=qian2;
ansl=l-1;
ansr=n-idx2+1;
else if(hou2>=qian2&&hou2>mx2)
mx2=hou2;
ansl=idx1;
ansr=n-r;
printf("%d %d\\n",ansl,ansr);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
E. Matrix and Shifts
题意:
有一个n*n的01矩阵,可以向四个方向循环移动矩阵,没有花费;使得某个位置的值去^1,花费1。
问最少花费多少,使得矩阵变成一个单位矩阵
思路:
我们记录初始每条斜线上1的个数和初始总共1的个数就行了,然后去暴力得到答案。因为斜线可以分类
n=4
1 2 3 4
4 1 2 3
3 4 1 2
2 3 4 1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+5;
int n;
char s[N][N];
void solve()
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%s",s[i]);
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(s[i][j]=='1') sum++;
int mi=n*n;
for(int i=0;i<n;i++)
int num=0;
for(int j=0;j<n;j++)
if(s[j][(i+j)%n]=='1') num++;
mi=min(mi,sum-num+n-num);
printf("%d\\n",mi);
int main()
int T;scanf("%d",&T);
while(T--) solve();
return 0;
F1. Promising String (easy version)
题意:
由字符’+‘和’-‘构成的长度为n字符串,有多少子字符串满足其中’+‘的数量等于’-‘的数量,
两个连续的’-‘字符可以替换成一个’+‘字符
思路:
暴力,枚举起始位置l,记录字符’+’、字符’-和’已经连续可以变换成’+‘的数量,同时记录一下当前连续’-'的数量,最后去判断就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e3+5;
int n;
char s[N];
void solve()
scanf("%d",&n);
scanf("%s",s+1);
int sum=0;
for(int l=1;l<=n;l++)
int nu0=0,nu1=0,lx=0,now=0;
for(int r=l;r<=n;r++)
if(s[r]=='+')
nu1++;
lx+=now/2;
now=0;
else
now++;
nu0++;
if(nu0==nu1) s以上是关于Codeforces Round #780 (Div. 3)(ABCDEF1F2)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #780 (Div. 3)(ABCDEF1F2)
Codeforces Round #780 (Div. 3)(ABCDEF1F2)
Codeforces Round #780 (Div. 3)(ABCDEF1F2)
Codeforces Round #780 (Div. 3) A-F2题解