Codeforces Round #825 (Div. 2) ABC
https://codeforces.com/contest/1736
A. Make A Equal to B
题目大意:
给定长度为n的01数组a和b;
操作有两种,一种是把0变成1或者把1变成1;
一种是按照自己的心意排一个序;
问我们能把a,b变成一样的数组的最小操作是多少?
input
5
3
1 0 1
0 0 1
4
1 1 0 0
0 1 1 1
2
1 1
1 1
4
1 0 0 1
0 1 1 0
1
0
1
output
1
2
0
1
1
感觉我的这个写法着实啰嗦哈哈
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=200200,M=2002;
LL a[N],b[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
int sum1=0,sum2=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum1+=a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
sum2+=b[i];
}
int ans=abs(sum1-sum2);
if(sum1==sum2)
{
bool flag=true;
for(int i=1;i<=n;i++)
if(a[i]!=b[i]) flag=false;
if(flag==false) cout<<ans+1<<endl;
else cout<<ans<<endl;
}
else if(sum1>sum2)
{
int k=ans;
for(int i=1;i<=n;i++)
{
if(b[i]==0&&a[i]==1)
{
b[i]=1;
k--;
}
if(k==0) break;
}
bool flag=true;
for(int i=1;i<=n;i++)
if(a[i]!=b[i]) flag=false;
if(flag==false) cout<<ans+1<<endl;
else cout<<ans<<endl;
}
else if(sum1<sum2)
{
int k=ans;
for(int i=1;i<=n;i++)
{
if(b[i]==1&&a[i]==0)
{
a[i]=1;
k--;
}
if(k==0) break;
}
bool flag=true;
for(int i=1;i<=n;i++)
if(a[i]!=b[i]) flag=false;
if(flag==false) cout<<ans+1<<endl;
else cout<<ans<<endl;
}
}
return 0;
}
B. Playing with GCD
题目大意:
给定一个长度为n的数组a,问我们能不能还原出一个长度为n+1的数组b,满足所有的
gcd{b[i],b[i+1]}==a[i];
能够构建出来就输出YES,不能就输出NO。
input
4
1
343
2
4 2
3
4 2 4
4
1 1 1 1
output
YES
YES
NO
YES
这个题目我直接猜了一把结论,没想到直接ac了,舒适
- 一开始毫无头绪的时候,我们可以先从题目的否定条件入手,什么时候才为NO呢?
- 4 2 4这个情况下就是因为我如果构建出4 4 2 ? 还是4 ? 4 4 都会存在一个地方不满足,因为我这两边的最小gcd都会比给定的数字要更大
所以我们可以想到,这肯定是三个三个相关的,而且我们对于中间的那个数字,他必须要大于等于我旁边两个数字和我的最大公约数的最大公约数 - 这是一种情况,还有一种就是如果是大于等于了,但是不是倍数关系呢?比如6 7 6,那必须也是不行的
- 否定条件判断成功,全部满足正确情况则为YES,否则为NO。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=200200,M=2002;
LL a[N],b[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
for(LL i=1;i<=n;i++)
{
cin>>a[i];
}
bool flag=true;
for(LL i=2;i<=n-1;i++)
{
LL l=a[i-1]*a[i]/__gcd(a[i-1],a[i]);
LL r=a[i+1]*a[i]/__gcd(a[i+1],a[i]);
LL num=__gcd(l,r);
//cout<<l<<" "<<r<<endl;
if(a[i]>=num&&a[i]%num==0) ;
else flag=false;
}
if(flag==true) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
C1. Good Subarrays (Easy Version)
题目大意:
给定一个长度为n的数组a,问我们可以构建多少个连续的数组b?满足里面的数字全部都b[i]>=i?
注意,选择的数字都必须是从左往右不间断的,形成新数组后下标相应改变。
input
3
3
1 2 3
3
1 1 1
4
2 1 4 3
output
6
3
7
经典的双指针,典型的跑右端点,左端点跟着动(佬儿教过我好多次啦哈哈,虽然第一发脑子抽了,想简单了)
但是第二发wa是因为没清空数组我是真的想不懂啊???(没道理啊!)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=200200,M=2002;
LL a[N],f[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
for(int i=1;i<=1e5+10;i++)
a[i]=0;
LL n;
cin>>n;
LL sum=0;
for(LL i=1;i<=n;i++)
cin>>a[i];
for(LL l=1,r=1;l<=n;l++)
{
while(a[r]>=(r-l+1))
{
sum+=(r-l+1);
r++;
}
}
cout<<sum<<endl;
}
return 0;
}