2023/1/6/codeforces冬令营第三次比赛复盘
I. The Humanoid(人形生物)
原题传送通道
思路:
1.将各个宇航员a[i]从小到大sort排序,减小Humanoid进食障碍
2.green=2,blue=1,创建b[3]={2,2,3}(注意,b中元素要从小到大排好队)
3.唯一影响答案ans不同的是Humanoid进食过程中对药丸的使用顺序,因此用next_permutation(b,b+3)对b中的元素进行排列组合A33次
4.对于b的每一种组合情况,药丸的使用原则是if(hh<a[i]&&j<3) hh*=b[j];j++;(hh(long long)是h的安全替身,鉴于h数据每次行动都要使用,让hh来作炮灰)
//
// Created by LION on 2023/1/6.
//
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,h,n,i,j;scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&h);
vector<int>b{2,2,3};
vector<long long>a(n);
for(i=0;i<n;i++){
scanf("%lld",&a[i]);
}sort(a.begin(),a.end());
int ans=0;
do
{
long long hh=h;
int mark=0;
for(i=0,j=0;i<n;){
if(hh>a[i]) hh+=a[i++]/2;
else if(j<3) hh*=b[j++];
else break;
mark=i;
}
ans=max(ans,mark);
}while(next_permutation(b.begin(),b.end()));
printf("%d\n",ans);
}
return 0;
}
F. Binary Inversions(01数组翻转)
原题传送通道
思路:
1.鉴于题目可能情况过于复杂,不是单单翻转左边第一个0为1或翻转右边第一个1为0就能解决的,我们首先求出原数组的inversion的数量max,一劳永逸(:
2.再从左到右遍历每一个元素,如果a[i]==1,ans=maxn-(i后面'0'的数量)+(i前面'1'的数量),反之亦然;每次ans=max(maxn,ans).
//
// Created by LION on 2023/1/6.
//
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+2;
int a[N];
int cnt(int n0,int n){
int ans=0;
for(int i=0;i<n;i++){
if(a[i]==0) n0--;
else ans+=n0;
}
return ans;
}
signed main(){
int t,i,j,n;scanf("%lld",&t);
while(t--){
int n0=0,n1=0;
scanf("%lld",&n);
for(i=0;i<n;i++){
scanf("%lld",&a[i]);
if(a[i]==0)n0++;
}
int ans=cnt(n0,n),c=0;
for(i=0;i<n;i++){
if(a[i]==1){
c=max(ans+n1-n0,c);
n1++;
}else{
c=max(c,ans-n1+n0-1);
n0--;
}
}
printf("%lld\n",max(ans,c));
}
return 0;
}
E. Challenging Valleys
原题链接
思路:
1.根据对valleys的定义,看似有3*2=6种情况符合valleys(3:l=0或0<l<=r<n-1或r=n-1。2:l=r或l<r),但再三思后整合在一起其实只有两种:l=r或l<r;
2.怎么整合呢?在a[i]数组两端分别加上一个无穷大;可自己画一下图理解一下;
3.最后对a[i],若满足a[i-1]<a[i]=...=a[j-1]<aj,则cnt++;最后判断cnt是否?=1;
//
// Created by LION on 2023/1/6.
//
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e9+2;
signed main(){
int t,i,j,n,r;cin>>t;
while(t--) {
cin >> n;
int l = 0, cnt = 0;
vector<int> a(n + 4, 0);
for (i = 1; i <= n; i++) {
cin >> a[i];
}
a[0]=N;a[n+1]=N;
j=n;
for(i=1;i<=j;i++){
if(a[i-1]>a[i]){
if(a[i+1]>a[i]) cnt++;
else if(a[i+1]==a[i]){
int ii=i+1;
while(a[ii]==a[i])ii++;
if(a[i]<a[ii]){cnt++;i=ii-1;}
}else continue;
}if(cnt>1){cout<<"NO"<<'\n';break;}
}if(cnt==1) {cout<<"YES"<<'\n';continue;}
}
return 0;
}
J.Make It Round
思路:
1.先求出当末尾 1 , 2 , 3... 1,2,3...1,2,3... 个 0 00 的需要的倍数,然后在依次扩大,lcm就是求最小倍数的数字,然后再每次一倍倍加即可,但是发现long long并不能满足我的需求,unsigned long long即可。
代码如下:
//
// Created by LION on 2023/1/6.
//
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
int main()
{
int T;cin>>T;
while(T--)
{
ULL n,m;cin>>n>>m;
ULL sum2=1;
ULL res=10;
for(int i=1;;i++)
{
ULL sum1=lcm(res,n)/n;
if(sum1>m) break;
res*=10;
sum2=sum1;
}
ULL sum=sum2;
for(int i=1;;i++)
{
if(sum+sum2>m) break;
sum+=sum2;
}
cout<<sum*n<<endl;
}
return 0;
}
K. Thermostat
原题通道
思路:
1.显然只有五种可能的答案:0、-1、1、2、3。
即要么无需操作,要么无解,要么最多只需要三步。
当a == b时,答案为0.
如果a和b的差值大于等于x,那么我们一步即可。
否则我们可能采取的操作有:
两步:先向高位或者低位方向移动,然后反向移动到b。
三步:先向高位/低位方向移动,然后再向低位/高位方向移动,再移动到b。
操作的前提是移动的时候不超过l和r。所以判断a、b和l、r之间的差值即可。
//
// Created by LION on 2023/1/6.
//
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e3 + 10;
const int INF = 0x3fffffff;
void solve()
{
int l, r, x, a, b;
cin >> l >> r >> x >> a >> b;
if (a == b)
{
cout << 0 << endl;
return;
}
if (abs(a - b) >= x)
{
cout << 1 << endl;
return;
}
if (b - l >= x && r - b >= x)
{
if (a - l >= x || r - a >= x)
cout << 2 << endl;
else
cout << -1 << endl;
}
else if (b - l >= x)
{
if(a - l >= x)
cout << 2 << endl;
else if(r - a >= x)
cout << 3 << endl;
else
cout << -1 << endl;
}
else if (r - b >= x)
{
if(r - a >= x)
cout << 2 << endl;
else if(a - l >= x)
cout << 3 << endl;
else
cout << -1 << endl;
}
else
cout << -1 << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << fixed;
cout.precision(18);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号