Educational Codeforces Round 134 (Rated for Div. 2)A-D

Dashboard - Educational Codeforces Round 134 (Rated for Div. 2) - Codeforceshttps://codeforces.com/contest/1721

A. Image

        一共四个字符,每次最多变一个或者两个相同字符到其他字符去,枚举所有情况就好了。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];


void solve(){
    char a;
    map<char,int>mm;
    for(int i = 1;i<=4;i++){
        cin>>a;
        mm[a]++;
    }
    if(mm.size()==4){
        cout<<3<<endl;
    }
    else if(mm.size()==3){
        cout<<2<<endl;
    }
    else if(mm.size()==2){
        cout<<1<<endl;
    }
    else if(mm.size()==1){
        cout<<0<<endl;
    }
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--)
        solve();
}

B. Deadly Laser

贪心一下,相当于这个陷阱覆盖的范围是一个斜着的正方形。一共两种走法,L和倒L,如果两种走法都走不了说明无论怎么走都会遇到这个陷阱

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];
int n,m,sx,sy,d;

int j = 0;
void solve(){
    j = 1;
    cin>>n>>m>>sx>>sy>>d;
    for(int i = 1;i<=n;i++){
        if(abs(i-sx)+abs(1-sy)<=d){
            j = 0;
            break;
        }
    }
    for(int i = 1;i<=m;i++){
        if(abs(n-sx)+abs(i-sy)<=d){
            j = 0;
            break;
        }
    }
    if(j){
        cout<<n+m-2<<endl;
        return;
    }
    j = 1;
    for(int i = 1;i<=m;i++){
        if(abs(1-sx)+abs(i-sy)<=d){
            j = 0;
            break;
        }
    }
    for(int i = 1;i<=n;i++){
        if(abs(i-sx)+abs(m-sy)<=d){
            j = 0;
            break;
        }
    }
    if(j){
        cout<<n+m-2<<endl;
        return;
    }
    cout<<-1<<endl;
    return;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--)
        solve();
}

C. Min-Max Array Transformation

最基础的匹配方式肯定是a[i]对b[i]这样子匹对上去,如果要找最小的,那么a[i]肯定要匹配b中比i下标小或者相等的位置。

直接用lowerbound就可以了,因为都是按顺序匹配的,找到a[i]和b[j]匹配后,j前面的仍然一一对应,i-j的部分让a[o]和b[o+1]匹配即可

更大的就不能这样使用,同理a[i]要匹配b中大于等于i的下标,同样构造

但是我们不能保证a[o]和b[o-1]一定能匹配上,因此我们用双指针即可。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
int num[maxn];
int a[maxn],b[maxn];
void solve(){
    int n;
    cin>>n;
    for(int i = 1;i<=n;i++)
        cin>>a[i];
    for(int i = 1;i<=n;i++)
        cin>>b[i];
    for(int i = 1;i<=n;i++){
        int pos = lower_bound(b+1,b+n+1,a[i])-b;
        cout<<b[pos]-a[i]<<" ";
    }
    cout<<endl;
    int j = 1;
    for(int i = 1;i<=n;i++){
        j = max(i,j);
        while(b[j]>=a[j+1]&&j<n)
            j++;
        cout<<b[j]-a[i]<<" ";
    }
    cout<<endl;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--)
        solve();
}

D. Maximum AND

ai和bi可以重新分组,也就意味着其实是让ai和bi进行配对,而这样的配对要尽可能让每一个ci的高位都为1,即优先第一高位为1,然后是第二第三。暴力处理一下

#include <bits\stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int a[maxn],b[maxn];
#define ll long long
void solve() {
    int n;
    cin>>n;
    for(int i = 1;i<=n;i++){
        cin>>a[i];
    }
    for(int i = 1;i<=n;i++){
        cin>>b[i];
    }
    int ans =  0;
    for(int i= 29;i>=0;i--){
        map<int,int>m;
        int now = ans|(1<<i);  //判断这样分组能不能满足前面确定的答案
        int ok = 1;
        for(int j = 1;j<=n;j++){
            m[a[j]&now]++; //这步感觉蛮巧妙的,首先把低位全部归0不考虑,高位如果之前给出的答案是0也归0不考虑
                            //如果是1的话就保留a中对应的0 1部分,在分组的时候进行考虑
        }
        for(int j = 1;j<=n;j++){
            int hh = (now&b[j])^now; //先&去掉不用考虑的部分,然后利用异或a^b =c a^c = b的性质看看能不能成功分组
            if(m.count(hh)){
                m[hh]--;
                if(m[hh]==0)
                    m.erase(hh);
            }
            else{
                ok = 0;
                break;
            }
        }
        if(ok)
            ans = now;
    }
    cout<<ans<<endl;
}

int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值