A - Destroying Bridges

水题,直接贪心,要么把1号岛周围的桥都断了,答案为1,要么就是n。

void solve(){
    CIN(n);CIN(k);
    cout<<((k>=n-1)?1:n)<<ET;
}

B - Equal XOR

题意:长度为 $n$ 的两个序列,$1$ 到 $n$ 的每个数恰好出现两次,让你在两边各选 $2k$ 个数,使得两部分其异或和相等。

异或和相等可以推出总异或和为 $0$,先按顺序排好两列数字,每段均从 $1$ 到 $n$,此时左右均取 $2k$ 个相同的数即可。若在两组数据交换任意两个不同的数,那么会两边的数据会同时多一对配对的数(它们异或和为 $0$),此时,在两边选取这些配对的数,和一些两边都有的数,也可以满足题意。

思路很好出,但是对码力还是由一点点要求的。

void solve(){//感觉代码没啥参考价值,建议自己按照文字说明写
    CIN(n);CIN(k);
    vector<int> a,b,oa;
    FOR(i,1,n){
        CIN(tmp);
        a.push_back(tmp);
    }
    FOR(i,1,n){
        CIN(tmp);
        b.push_back(tmp);
    }
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    map<int,bool> ao,bo;
    int cnt=0;
    FOR(i,0,n-1){
        if(i+1<n&&a[i]==a[i+1]){
            ao[a[i]]=1;
            i++;
            cnt++;
        }
    }
    FOR(i,0,n-1){
        if(i+1<n&&b[i]==b[i+1]){
            bo[b[i]]=1;
            i++;
        }
    }

    if(cnt>=k){
        cnt=k;
        FOR(i,0,n-1){
            if(cnt==0)break;
            if(i+1<n&&a[i]==a[i+1]){
                cout<<a[i]<<" "<<a[i]<<" ";
                i++;
                cnt--;
            }
        }
        cout<<ET;
        cnt=k;
        FOR(i,0,n-1){
            if(cnt==0)break;
            if(i+1<n&&b[i]==b[i+1]){
                cout<<b[i]<<" "<<b[i]<<" ";
                i++;
                cnt--;
            }
        }
        cout<<ET;
    }else{
        int cnt_=cnt;

        cnt=(k-cnt_)*2;
        FOR(i,0,n-1){
            if(cnt==0)break;
            if(i+1<n&&a[i]==a[i+1]&&cnt){
                i++;
            }else{
                cout<<a[i]<<" ";
                cnt--;
            }
        }
        for(auto &[i,askjldfhklj]:ao){
            cout<<i<<" "<<i<<" ";
        }

        cout<<ET;
        cnt=(k-cnt_)*2;
        FOR(i,0,n-1){
            if(cnt==0)break;
            if(i+1<n&&b[i]==b[i+1]&&cnt){
                i++;
            }else{
                cout<<b[i]<<" ";
                cnt--;
            }
        }
        for(auto &[i,askjldfhklj]:bo){
            cout<<i<<" "<<i<<" ";
        }
        cout<<ET;
    }
}

C - MEX Game 1

简单博弈,先排序。

  • 对于只出现一次的数,Alice如果不拿,Bob肯定会优先拿掉这个。
  • 对于出现了两次以上的数,Bob拿它是没有意义的,因为拿了还有剩,那么Alice在Bob拿了后跟着拿掉这个数,Bob就相当于浪费了那次机会。

所以Bob会优先选择最小的,只出现了一次的数。

然后对 $0$ 的数量分类讨论:

  • 如果没有 $0$,那么答案就是 $0$。
  • 如果只有一个 $0$,那么Alice必须先拿这个0,然后再看Bob拿哪个,自己就拿哪个。
  • 如果有两个以上的 $0$ 那么Alice就可以先救回最小的只出现一次的数,再跟着Bob取其它数。

然后就是一些小小的特判就行。

int b[200005];
void solve(){
    CIN(n);
    memset(b,0,sizeof b);
    FOR(i,1,n){
        CIN(tmp);b[tmp]++;
    }

    if(b[0]==0){cout<<0<<ET;return;}//0为0,输出0
    if(b[0]==1){//0为1,Alice没有操作空间,最大收益就是第一个出现次数小于2的数
        FOR(i,1,n){
            if(b[i]<2){
                cout<<i<<ET;return;
            }
        }        
    }else{//0大于1,Alice有能力救某个数量为1的数
        bool flag=0;
        FOR(i,1,n){
            if(!flag){//只能救一次,所以插个flag记录一下有没有使用过这次机会
                if(b[i]==1){
                    flag=1;
                }
                if(b[i]==0){//注意这种情况,Alice是没法救的
                    cout<<i<<ET;return;
                }
            }else{
                if(b[i]<2){
                    cout<<i<<ET;return;
                }
            }
        }
    }
}

附录

这里贴上头部定义和main函数部分:

#include<iostream>
#include<vector>
#include<bits\stdc++.h>
#define ll long long
#define ld long double
using namespace std;
#define ET '\n'
#define FOR(i,a,b) for(ll i=(a);i<=(b);i++)
#define rFOR(i,a,b) for(ll i=(a);i>=(b);i--)
#define CIN(a) ll a;cin>>a
#define DCIN(a) ld a;cin>>a
#define CA cout<<ans<<ET
#define CY cout<<"YES"<<ET
#define CN cout<<"NO"<<ET
//没有C++20就不能用ranges了
//#define PP(l,r,CK) *ranges::partition_point(ranges::iota_view((l),(r)+1),(CK))
string ANS[2]={"No\n","Yes\n"};

//solve函数代码

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //pre();
    CIN(t);while(t--)
    solve();
    return 0;
}