A. green_gold_dog, array and permutation

题意: 给一个数组a,确定一个排列b,使得ai-bi所形成的ci中不同的元素的给额数最大

思路:将a数组按照值排序,最小的放n,依次放b,最后按照i排序输出答案

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
bool  cmp1(pair<int,int>x,pair<int,int>y){
    return x.first<y.first;
}
bool  cmp2(pair<int,int>x,pair<int,int>y){
    return x.second<y.second;
}
void solve(){
    int n;
    cin>>n;
    vector<pair<int,int>>q;
    for (int i = 1; i <=n ; ++i) {
        int x;
        cin>>x;
        q.push_back({x,i});
    }
    sort(q.begin(),q.end(),cmp1);
    for (int i = 0; i <n ; ++i) {
        q[i].first=n-i;
    }
    sort(q.begin(),q.end(),cmp2);
    for (auto i:q) {
        cout<<i.first<<' ';
    }
    cout<<endl;
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

B. XOR Palindromes

题意:给一个字符串,你的目的是要把他变成回文串,你有一个操作是将0或1取反,问当操作次数是i次时,是否可以将字符串变为回文串

思路:我们先对非回文的地方进行统计个数cnt,当我们的操作次数>=cnt

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
bool  cmp1(pair<int,int>x,pair<int,int>y){
    return x.first<y.first;
}
bool  cmp2(pair<int,int>x,pair<int,int>y){
    return x.second<y.second;
}
void solve(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    int cnt=0;
    for (int i = 0; i <n/2 ; ++i) {
        if(s[i]!=s[n-i-1]){
            cnt++;
        }
    }
//    cout<<cnt<<endl;
    if (n&1) {
        for (int i = 0; i <= n; ++i) {
            if (i >= cnt && n - i >= cnt) {
                cout << "1";
            } else {
                cout << "0";
            }

        } cout << '\n';
        return;
    }

    else {
        int vis=0;
        for (int i = 0; i <= n; ++i) {
            if (i >= cnt && n - i >= cnt) {
                if(vis&1)cout<<'0';
                else cout<<'1';
                vis++;
            } else {
                cout << "0";
            }

        }
        cout << '\n';
        return;
    }

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

C. Salyg1n and the MEX Game

题意:交互题,Alice和Bob游戏,刚开始是有n个数字,Alice是加入数字,Bob要删除数字,Alice是要MEX最大化,而Bob要MEX最小化,问游戏结束时或者进行了2 * n+1次时,MEX是多大,游戏结束时输出-1,你要做Alice,Bob是机器,你选择加入一个数字,他选择删除一个数字

思路:因为两者都有优先选择的方法,那么其实答案只能是原数字的MEX值+1,我们加入就是加这个数,他删也是只能删除这个数字,最后-1结束

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int n;
    cin>>n;
    set<int>st;
    for (int i = 0; i <n ; ++i) {
        int x;
        cin>>x;
        st.insert(x);
    }
    int vis=0;
    int mex=0;
    int biaozhi;
    for (int i = 0; i <=n ; ++i) {
        if(st.count(i)==1){
            mex++;
        }
        else{
            if(vis==0){
                biaozhi=i;
                mex++;
                vis=1;
            }
            else{
                break;
            }
        }
    }
    cout<<biaozhi<<endl;
    int x;
    for (int i = 0; i <n ; ++i) {
        cin>>x;
        if(x==-1){
            return;
        }
//        if(x==-2)exit(0);
        cout<<x<<endl;
    }
    cin>>x;
    return;
//    cout<<mex<<endl;
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

D. Cyclic Operations

题意:给定一个长度位n的数组b,和一个数字k,同时有一个a数组,起初a数组为0,你可以进行无数次操作,构造出一个长度为k的数组L,令aLi=L(i%k+1);问是否可以使得a与b相等呢

思路:给定的表达式,可以想到环的内容,类似 2 4 3 1,2 4 1 是一个内部的环,2->4,4->1,1->2这样建边,然后然后对3,不是一个环,那么就可以先借用他连通的环,先修改当前的数,然后再修改环内的数,因此直接拓扑序求一下环的大小即可,环的大小必须是k,如果k=1时,那么任何数字都是一个自环才可以

diamond:

#include<bits/stdc++.h>
using namespace std;
//#define int long long
void solve()
{
    int n,k;
    cin>>n>>k;
    vector<int>g(n+1);
    vector<int >d(n+1);
    vector<int >a(n+1);
    for (int i = 1; i <=n ; ++i) {
        cin>>a[i];
    }
    for (int i = 1; i <=n ; ++i) {
        g[a[i]]=a[a[i]];
    }
    for (int i = 1; i <=n ; ++i) {
        d[g[i]]++;
    }
    if(k==1)
    for (int i = 1; i <=n ; ++i){
        if(i!=g[i]){
            cout<<"NO\n";
            return;
        }
    }
    queue<int>q;
    for (int i = 1; i <=n ; ++i) {
        if(!d[i]){
            q.push(i);
        }
    }
    while (!q.empty()){
        auto t=q.front();
        q.pop();
        d[g[t]]--;
        if(!d[g[t]]){
            q.push(g[t]);
        }
    }
    for (int i = 1; i <=n ; ++i) {
        if(d[i]){
            int cnt=1;
            int dq=i;
            d[i]--;
            while (1){
                if(d[g[dq]]){
                    cnt++;
                    d[g[dq]]--;
                }
                else break;
                dq=g[dq];
            }
            if(cnt!=k){
                cout<<"NO\n";
                return;
            }
        }
    }
    cout<<"YES\n";
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
}
 

E1. Salyg1n and Array (simple version)

题意:交互题,给一个n和k,你的目的是得到数组大小为n的数组a的异或和,每次你可以询问一个位置i,会返回给你这个数组从i到i+k-1的异或和,并且将这些数的相对位置颠倒,你必须在不超过100次的询问之中得到答案,假设我们的$n%k==0$时,我们可以直接进行询问,记录异或和即可,例如n=6,k=2,我们询问1,3,5;但当n=8,k=6时,我们这样询问一次,1 2 3 4 5 6 7 8,我们询问第一次 1,得到1 2 3 4 5 6的异或和,然后得到6 5 4 3 2 1 7 8,然后我们考虑如何得到 7 8,我们可以这样询问,首先询问 2,得到 5 4 3 2 1 7的异或和,然后变成 6 7 1 2 3 4 5 8,然后我们再询问3 ,得到 1 2 3 4 5 8,变成 5 6 7 4 3 2 1 8,然后就可以得到了 7 8的异或和了,期间的1 2 3 4 5异或了偶数次,被抵消,这样即可在100次以内拿下

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
    int n,k;
    cin>>n>>k;
    int ans=0;
    int x;
    for (int i = 1; i <=n-k+1; i+=k) {
        cout<<"? "<<i<<endl;
        cin>>x;
        ans^=x;
    }
    if(n%k==0){
        cout<<"! "<<ans<<endl;
        return;
    }
    else{
        int g=n/k;
        g--;
        for (int i = 2+g*k; i <=2+g*k+n%k-1 ; ++i) {
            cout<<"? "<<i<<endl;
            cin>>x;
            ans^=x;
        }
        cout<<"! "<<ans<<endl;
        return;
    }
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
}

E2. Salyg1n and Array (hard version)

题意:与上题一样,只不过100次变为50次

思路:前面不变,但后面可以这样考虑,n=8,k=6,首先对1 进行操作,1 2 3 4 5 6 7 8,得到6 5 4 3 2 1 7 8,然后我们这样操作,对3操作,得到的异或和,然后变成6 5 7 1 2 3 4 8 ,得到7 1 2 3 4 的异或和,然后对4进行操作,得到 1 2 3 4 8的异或和,得出答案,即对n-k-g/2+1操作,和对n-k-1操作,g为n%k

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
    int n,k;
    cin>>n>>k;
    int ans=0;
    int x;
    for (int i = 1; i <=n-k+1; i+=k) {
        cout<<"? "<<i<<endl;
        cin>>x;
        ans^=x;
    }
    if(n%k==0){
        cout<<"! "<<ans<<endl;
        return;
    }
    else{
        int g=n%k;
        cout<<"? "<<n-k-g/2+1<<endl;
        cin>>x;
        ans^=x;
        cout<<"? "<<n-k+1<<endl;
        cin>>x;
        ans^=x;
        cout<<"! "<<ans<<endl;
        return;
    }
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
}
 
posted on 2023-09-21 13:14  IR101  阅读(29)  评论(0编辑  收藏  举报  来源