Codeforces Round 994 (Div. 2)前四道

A. MEX Destruction

翻译:

        龙 Evirir 溜进了一个巫师的城堡,发现了一个神秘的装置,他们玩耍的本能使他们玩弄(摧毁)了它...

        埃维龙发现了一个由 n 个非负整数组成的数组 a_{1},a_{2},...,a_{n}

        在一次操作中,他们可以选择 a 的一个非空子数组∗ b,并用整数 mex(b)† 取而代之。他们希望多次使用这一操作,使 a 只包含零。可以证明,在问题的约束条件下,这总是可行的。

        所需的最少运算次数是多少?

思路:

对于一个不存在0的子数组进行mex会得到0。

都只有0时,运算次数为0。

当只有1段无0子数组时,运算次数为1。

当有1段以上的子数组时,运算次数为2。

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
void solve(){
	int n,ans=0;
	cin>>n;
  vector<int> a(n+1,0);
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++){
		if(a[i]!=0&&a[i-1]==0)ans++;
	}
	if(ans>1)ans=2;
	cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 中间填保留几位小数,不填默认
    // cout.precision();
    int t;cin>>t;
    while (t--) solve();
}

B. pspspsps

 翻译:

猫会被ppspsps吸引,但埃维里尔作为一条高贵的龙,只会被有奇怪特定要求的ppspsps吸引...

给定一个长度为 n 的字符串 s=s_{1}s_{2}...s_{n} 由字符 p、s 和 .(点)组成,判断是否存在长度为 n 的排列∗ p,使得对于所有整数 i(1≤i≤n):

  • s_{i} 为 p,则 [p_{1},p_{2},...,p_{i}]构成一个长度为 i 的排列;
  • 如果 s_{i} 是 s,那么 [p_{i},p_{i+1},...,p_{n}]构成一个排列(长度为 n-i+1);
  • 如果 s_{i} 为 .,则没有额外的限制。

思路:

符号p代表左侧(l)的所有数字为排列,而s代表右侧(r)的所有数字为排列。当存在p在s左侧的情况(不包括两端)时为NO

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
 
void solve(){
  int n;
  string s;
  cin>>n;
  cin>>s;
  int l = -1,r = -1;
  for (int i=0;i<n;i++){
    if (s[i]=='s') l = i;
    if (r==-1&&s[i]=='p') r = i;
  }
  if (l!=-1 && r!=-1){
    if (l==0||r==n-1){
      cout<<"YES"<<endl;
    }else{
      cout<<"NO"<<endl;
    }
  }else{
    cout<<"YES"<<endl;
  }
}
 
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 中间填保留几位小数,不填默认
    // cout.precision();
    int t;cin>>t;
    while (t--) solve();

C. MEX Cycle

 翻译:

        龙 Evirir 有很多朋友。他们有 3 个朋友!比普通龙多一个。

        给你一个整数 n、x 和 y。有 n 条龙围成一个圆圈。龙的编号为 1、2、......、n。对于每个 i(1≤i≤n),龙 i 与龙 i-1 和 i+1 为好友,其中龙 0 定义为龙 n,龙 n+1 定义为龙 1。此外,龙 x 和龙 y 也是彼此的朋友(如果它们已经是朋友,则不会有任何变化)。请注意,所有好友关系都是相互的。

        输出 n 个非负整数 a_{1},a_{2},...,a_{n},使得每条龙 i(1≤i≤n)的下列条件成立:

  • f_{1},f_{2},...,f_{k}为龙 i 的朋友。则 a_{i}=mex(a_{f_{1}},a_{f_{2}},...,a_{f_{k}}).∗

思路:

分类讨论:

  1. x,y相邻
    1. n为偶数(even)
      1. 使用010101循环
    2. n为奇数(odd)
      1. 下标1使用2,之后使用01循环
  2.  x,y不相邻
    1. x到y的两条路径中所蕴涵的元素数量都为奇数
      1. 从x到y两路径都使用01循环,0开始(包括x),对于下标y赋值为2
    2. x到y的两条路径中所蕴涵的元素数量都为偶数
      1. x到y的两路径一条使用01循环,一条使用10循环(都不包括x),对于下标x赋值为2,y赋值为3
    3. x到y的两条路径中所蕴涵的元素数量为一奇数,一偶数
      1. 从x到y两路径都使用01循环,0开始(包括x),下标y赋值为2

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;

void solve(){
  int n,x,y;
  cin>>n>>x>>y;
  vector<int> a(n+1);
  if (x+1==y || (x>1&&x-1==y) || x==1&&y==n){
    if (n%2==0){
      int cnt = 0;
      for (int i=1;i<=n;i++){
        a[i] = cnt;
        cnt^=1;
      }
    }else{
      int cnt = 0;a[1] = 2;
      for (int i=2;i<=n;i++){
        a[i] = cnt;
        cnt ^= 1;
      }
    }
  }else{
    if ((y-x-1)%2 && (n-(y-x+1))%2){
      int cnt = 0;
      for (int i=x;i<y;i++){
        a[i] = cnt;
        cnt ^= 1;
      }
      cnt = 0;
      for (int i=x;i!=y;i = (i==1 ? n : i-1)){
        a[i] = cnt;
        cnt ^= 1;
      }
      a[y] = 2;
    }else if ((y-x-1)%2==0 && (n-(y-x+1))%2==0){
      int cnt = 1;
      for (int i=x+1;i<y;i++){
        a[i] = cnt;
        cnt ^= 1;
      }
      cnt = 0;
      for (int i=(x==1 ? n : x-1);i!=y;i = (i==1 ? n : i-1)){
        a[i] = cnt;
        cnt ^= 1;
      }
      a[x] = 2;
      a[y] = 3;
    }else{
      int cnt = 0;
      for (int i=x;i<y;i++){
        a[i] = cnt;
        cnt ^= 1;
      }
      cnt = 0;
      for (int i=x;i!=y;i = (i==1 ? n : i-1)){
        a[i] = cnt;
        cnt ^= 1;
      }
      a[x] = 0;
      a[y] = 2;    
    }
  }
  for (int i=1;i<=n;i++){
    if (i!=1) cout<<" ";
    cout<<a[i];
  }cout<<endl;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 中间填保留几位小数,不填默认
    // cout.precision();
    int t;cin>>t;
    while (t--) solve();
}

 D. Shift + Esc

翻译:

        龙 Evirir 在玩弄了某种装置并被抓住后,决定好好利用他们的魔法技能--扭曲现实以快速逃脱!

        给你一个网格,网格中有 n 行、m 列非负整数和一个整数 k。让 (i,j) 表示从上到下第 i 行和从左到右第 j 列中的单元格(1≤i≤n, 1≤j≤m)。对于每个单元格 (i,j),整数 ai,j 都写在单元格 (i,j) 上。

        您最初位于 (1,1),想要移动到 (n,m)。您只能向下或向右移动。也就是说,如果您在 (i,j),您只能移动到 (i+1,j) 或 (i,j+1)(如果存在相应的单元格)。

        在开始移动之前,您可以多次执行以下操作:

  • 在 1 到 n 之间选择一个整数 i,将第 i 行向左循环移动 1。形式上,对于所有整数 j(1≤j≤m),使 a_{i,j}变为 a_{i,(j\ mod\ m)+1}

        注意,开始移动后不得进行任何操作。
        从(1,1)移动到(n,m)后,设 x 为移动前进行的操作次数,y 为写在已访问单元格(包括(1,1)和(n,m))上的整数之和。那么成本定义为 kx+y。

        求从 (1,1) 移动到 (n,m) 的最小成本。

思路:

考虑当前i行向左第shift次后的结果tmp,dp[i][j]都可能由(上面的元素)(dp[i-1][j]+当前的元素+当前行向左移动的次数)或(左面的元素)(dp[i][j-1]+当前的元素+当前行向左移动的次数)构成,

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;

void solve(){
  ll n,m,k;cin>>n>>m>>k;
  vector<vector<ll>> a(n+1,vector<ll>(m)),dp(n+1,vector<ll>(m+1,1e18));
  for (ll i=1;i<=n;i++){
    for (ll j=0;j<m;j++){
      cin>>a[i][j];
    }
  }    
  dp[0][0] = 0;
  for (ll i=1;i<=n;i++){
    for (ll shift=0;shift<m;shift++){
      vector<ll> tmp(m,1e18);
      for (ll j=0;j<m;j++) tmp[j] = dp[i-1][j]+a[i][(j+shift)%m];
      for (ll j=0;j<m;j++) tmp[j] = min(tmp[j],tmp[(j+m-1)%m]+a[i][(j+shift)%m]);
      for (ll j=0;j<m;j++) dp[i][j] = min(dp[i][j],tmp[j]+k*shift);
    }
  }
  cout<<dp[n][m-1]<<endl;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 中间填保留几位小数,不填默认
    // cout.precision();
    ll t;cin>>t;
    while (t--) solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cando-01

随心而动,随性而为。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值