0
点赞
收藏
分享

微信扫一扫

Codeforces Global Round 10(A->D(环问题))

盖码范 2022-09-26 阅读 171

A:​​http://codeforces.com/contest/1392/problem/A​​

题意:

相邻的不同数可以相加合成一个数,问最后最少会剩下几个数

解析:

随便写一下,就会发现,只要数组中只要存在不同数,最后就一定能合成一个数。

所以,全相等,输出n,否则1

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=2e5+20;
//const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
int ok=0;
for(int i=1;i<=n;i++)
cin>>a[i];
if(n==1)
{
cout<<"1"<<endl;continue;
}
for(int i=2;i<=n;i++)
{
if(a[i]!=a[i-1])
{
ok=1;break;
}
}
if(ok)
cout<<"1"<<endl;
else
cout<<n<<endl;

}
}

B:​​http://codeforces.com/contest/1392/problem/B​​

题意:

每次操作让当前数组的最大值去减数组的每一个数,求第k次操作的数组

解析:

列了一下,发现,k=1,变一次,k=2,变两次,k=3,变三次

对于k>1,奇数变三次,偶数变两次

模拟一下即可。

关于最大值的选择,不少人赛后被hack掉,所以建议最大值直接设为a[1]妥当。

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=2e5+20;
//const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
ll k;
cin>>n>>k;
ll maxx;
cin>>a[1];
maxx=a[1];
for(int i=2;i<=n;i++)
cin>>a[i],maxx=max(a[i],maxx);
if(k==1)
{
for(int i=1;i<=n;i++)
{
cout<<maxx-a[i]<<' ';
}
cout<<endl;continue;
}
ll maxx2=maxx-a[1];
a[1]=maxx-a[1];
for(int i=2;i<=n;i++)
{
a[i]=maxx-a[i];
maxx2=max(maxx2,a[i]);
}
ll maxx3=maxx2-a[1];
a[1]=maxx2-a[1];
for(int i=2;i<=n;i++)
{
a[i]=maxx2-a[i];
maxx3=max(maxx3,a[i]);
}
if(k%2==0)
{
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;continue;
}
ll maxx4=maxx3-a[1];
a[1]=maxx3-a[1];
for(int i=2;i<=n;i++)
{
a[i]=maxx3-a[i];
maxx3=max(maxx3,a[i]);
}
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
}

C:​​http://codeforces.com/contest/1392/problem/C​​

题意:

给出序列,操作:对不递减的区间里的每一个数都加1,将整个序列变成非递减序列所需要的最少操作数。

解析:

本来分析复杂了,涉及到区间问题。但是把序列倒着遍历,思路就很清晰了。

ai<ai-1,把ai增加到和ai-1相同。

以后再遇到这种情况,ai后集体跟着加1即可。

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=2e5+20;
//const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
ll ans=0;
for(int i=n;i>1;i--)
{
if(a[i]<a[i-1])
ans+=(a[i-1]-a[i]);
}
cout<<ans<<endl;
}
}

D:​​http://codeforces.com/contest/1392/problem/D​​

题意:

n个人围成一圈。字符串表示每个人攻击的是左边的人还是右边的人。

合法情况:

如果一个人被攻击一次,那么他要反击那个人

如果一个人被攻击0或两次,他可以对左右任选一个攻击。

将游戏变成合法,最少需要纠正几个人?

解析:

先把环变成链

1:全L或全R的情况,

RRR->RRL,RRRR->RRLL,RRRRR->RRLRL , RRRRRR->RRLRRL

有结论,此时结果为:n/3+(n%3>0)

2:L和R均有

借助1的结论,固定到第一个a[k]!=a[0],往后记录连续和a[k]相等的,cnt++

a[i]!=a[k],记录总数sum+=cnt/3,cnt重置,k改变

注意对于cnt<3,是不需要改的,这部分肯定是符合条件的。

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=2e5+20;
char s[3*maxn];
//const ll inf=0x3f3f3f3f3f3f3f3f;
ll a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
// string s;
int n;
cin>>n;
scanf("%s",s);
for(int i=0;i<n;i++)
s[i+n]=s[i];
int k=-1;
for(int i=1;i<n;i++)
{
if(s[i]!=s[0])
{
k=i;
break;
}
}
if(k==-1)
{
cout<<n/3+(n%3>0)<<endl;
continue;
}
int id=k;
ll sum=0;
int cnt=0;
for(int i=k;i<n+k;i++)
{
if(s[i]==s[id])
cnt++;
else
{
sum+=cnt/3;
cnt=1;
id=i;
}
}
sum+=cnt/3;
cout<<sum<<endl;
}
}

 



举报

相关推荐

0 条评论