Codeforces Round 945 (Div. 2)

Codeforces Round 945 (Div. 2)

A. Chess For Three 签到

题意

三个人两两下棋,胜者得 2 分,败者得 0 分,平局双方各得 1 分。 现在给你三个人的得分(已经升序排序)。

求最多平局个数,如果得分不合法输出 1

思路

考虑两种情况,

a+b>=c 时:两人分别和 c 去和棋,剩下部分两个人互相和棋。如果剩余为奇数,那么说明不合法。

a+b<c 时:两人分别和 c 去和棋,c 剩下部分得分去战胜别人获得,如果剩余为奇数,那么说明不合法。

代码

#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;

typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 1;

void Showball(){
   int a,b,c;
   cin>>a>>b>>c;
   int t=a+b-c;
   if(t&1) return cout<<"-1\n",void();
   if(t<0) cout<<a+b<<endl;
   else cout<<c+(a+b-c)/2<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    if(cases) cin>>T;
    while(T--)
    Showball();
    return 0;
}

B. Cat, Fox and the Lonely Array 拆位+贪心

题意

给你 n 个非负整数,求出满足每 k 个连续元素按位或的结果相等的最小 k 值。

思路

位运算题目,拆位,这样整数的取值只有 01 , 那么按位或的值只有 01 两种取值。

对于 0 这种情况,必须所有值全部为 0 ,此时 k=1

对于 1 这种情况,贪心考虑,显然最小的 k 就是最长连续 0 的长度 + 1

最长连续 0 的长度用双指针维护即可。

代码

void Showball(){
   int n;
   cin>>n;
   vector<int> a(n);
   for(int i=0;i<n;i++) cin>>a[i];
   int ans=1;
   for(int i=0;i<=20;i++){
      for(int j=0;j<n;j++){
         int cnt=1,k=j;
         while(k<n&&!(a[k]>>i&1)) cnt++,k++;
         if(cnt==n+1) cnt=1;
         ans=max(ans,cnt);
         if(j==k) continue;
         j=k-1;
      }
   }
   cout<<ans<<endl;
}

C. Cat, Fox and Double Maximum

题意

给你一个长度为 n 的排列 p, 构造一个新的长度为 n 的排列 q ,不妨令 ai=pi+qi

若满足 ai1<ai 并且 ai>ai+1 那么我们称 ai 为局部最大值。请你构造出 q 使得局部最大值的数量最大。

思路

为了使得局部最大值的数量最多,那么局部最大值一定全部排在奇数位或者偶数位。

如果 1 在奇数位,我们就构造局部最大值在偶数位。反之,将局部最大值构造在奇数位。

这里假设 1 在奇数位,那么我们将 1 ~ n/2 之间的数全部安排在奇数位上,并且按照 pi 值降序安排。

这样就可以保证奇数位的所有数都是小于等于 n+1 的。

接着将 n/2+1 ~ n 之间的数全部安排在偶数位上,并且按照 pi 值降序安排。

这样就可以保证偶数位的所有数都是大于 n+1 的。那么偶数位就全部满足局部最大值的性质了。

如果 1 在偶数位,反过来处理即可。

代码

void Showball(){
   int n;
   cin>>n;
   vector<int> a(n+1);
   vector<PII> odd,even;
   int ok=0;
   for(int i=1;i<=n;i++){
     cin>>a[i];
     if(a[i]==1) ok=i&1;
     if(i&1) odd.pb({a[i],i});
     else even.pb({a[i],i});
   }
 
   sort(all(odd));
   sort(all(even));
   vector<int> ans(n+1);
   int t=(ok?n/2:n);
   for(auto [v,p]:odd) ans[p]=t--;
   t=(ok?n:n/2);
   for(auto [v,p]:even) ans[p]=t--;
   for(int i=1;i<=n;i++) cout<<ans[i]<<" \n"[i==n];
}

D. Cat, Fox and Maximum Array Split 交互题

题意

给你 nk , 有一个隐藏的数组 a ,定义 f(l,r)=(rl+1)·maxx=lrax

你可以进行 2n 次询问,每次询问给出 l,x 返回一个整数 p ,满足 f(l,r)=x 的最小正整数 r

若不存在这样的 r , 返回 n+1

通过询问后,你需要找到或者确定不存在这样的 m 。使得将数组分割成 k 个子数组,使得所有子数组 li,ri ,满足 f(li,ri)=m

思路

考虑答案只可能为最大值的倍数,那么我们就可以询问 n 次找到最大值。然后枚举倍数,因为最多只用枚举到

n/k 倍,所以询问次数不会超过 2n 次。然后判断,维护答案即可。

代码

void Showball(){
   int n,k;
   cin>>n>>k;
   
   auto ask=[&](int l,int x){
     cout<<"? "<<l<<" "<<x<<endl;
     int ret;
     cin>>ret;
     return ret;
   };

   int maxn=0;
   for(int i=1;i<=n;i++){
     if(ask(1,i*n)==n){
       maxn=i;
       break;
     }
   }

   int ans=-1;
   for(int i=1;i<=n/k;i++){
     int m=i*maxn;
     int cnt=0,r=1;
     while(r<=n){
      r=ask(r,m);
      if(r==n+1){
        cnt=0;
        break;
      }
      r++;
      cnt++;
      if(cnt==k&&r!=n+1){
        cnt=0;
        break;
      }
     }
     if(cnt==k) ans=max(ans,m);
   }
   cout<<"! "<<ans<<endl;
   int t;
   cin>>t;
}
posted @   Showball  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek智能编程
· 精选4款基于.NET开源、功能强大的通讯调试工具
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
点击右上角即可分享
微信分享提示