Codeforces Round 967 Div. 2 题解(A~D)

传送门

A. Make All Equal

题目

You are given a cyclic array a1,a2,…,an.

You can perform the following operation on a at most n−1 times:

  • Let m be the current size of a, you can choose any two adjacent elements where the previous one is no greater than the latter one (In particular, am and a1 are adjacent and am is the previous one), and delete exactly one of them. In other words, choose an integer i(1≤i≤m) where ai≤a(imodm)+1 holds, and delete exactly one of ai or a(imodm)+1 from a.

Your goal is to find the minimum number of operations needed to make all elements in aa equal.

思路

因为是循环数组,任意两个值不同的点,无论是值小的排前面还是值大的排前面,最后都能消掉。题目需要找最小操作次数使得数组当中的值都相同,则只要找最大的值相同的数量,n-数量就是需要消掉的数量也就是答案。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=110;
int a[N];
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        sort(a+1,a+1+n);
        int ans=1,p=1;
        for(int i=2;i<=n;i++){
            if(a[i]!=a[i-1]){
                ans=max(ans,i-p);
                p=i;
            }
        }
        ans=max(ans,n+1-p);
        cout<<n-ans<<'\n';
    }
    return 0;
}

B. Generate Permutation

题目

There is an integer sequence a of length n, where each element is initially −1.

Misuki has two typewriters where the first one writes letters from left to right, with a pointer initially pointing to 1, and another writes letters from right to left with a pointer initially pointing to n.

Misuki would choose one of the typewriters and use it to perform the following operations until aa becomes a permutation of [1,2,…,n]

  • write number: write the minimum positive integer that isn’t present in the array aa to the element ai, i is the position where the pointer points at. Such operation can be performed only when ai=−1.
  • carriage return: return the pointer to its initial position (i.e. 1 for the first typewriter, n for the second)
  • move pointer: move the pointer to the next position, let i be the position the pointer points at before this operation, if Misuki is using the first typewriter, i:=i+1 would happen, and i:=i−1 otherwise. Such operation can be performed only if after the operation, 1≤i≤n holds.

Your task is to construct any permutation p of length n, such that the minimum number of carriage return operations needed to make a=p is the same no matter which typewriter Misuki is using.

思路

找规律这题,这题看数据猜前半段奇,后半段偶,n也得是奇数,如果n是偶数凑不出来输出-1.

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        if(n%2==0)cout<<-1<<'\n';
        else{
            int x=n;
            cout<<x;
            x-=2;
            for(int i=2;i<=n/2+1;i++){
                cout<<' '<<x;
                x-=2;
            }
            x=2;
            for(int i=1;i<=n/2;i++){
                cout<<' '<<x;
                x+=2;
            }
            cout<<'\n';
        }
    }
    return 0;
}

C. Guess The Tree

题目

This is an interactive problem.

Misuki has chosen a secret tree with n nodes, indexed from 1 to n, and asked you to guess it by using queries of the following type:

  • “? a b” — Misuki will tell you which node xx minimizes |d(a,x)−d(b,x)|, where d(x,y) is the distance between nodes x and y. If more than one such node exists, Misuki will tell you the one which minimizes d(a,x).

Find out the structure of Misuki’s secret tree using at most 15n queries!

思路

给的n很小,2的10次方>1000,所以每个点找从1到这个点的中间节点,再找从这个中间节点到这个点的中间节点,一直找到中间节点就是两个被查找的节点中前一个节点,总的查询次数也不会超过10,因此可以暴力查找出每个节点的父节点。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e4+5;
int fa[N];
void query(int u,int v){
    while(1){
        cout<<"? "<<u<<' '<<v<<endl;
        int d;
        cin>>d;
        if(d!=u)u=d;
        else{
            fa[v]=d;
            break;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)fa[i]=-1;
        for(int i=2;i<=n;i++){
            if(fa[i]==-1){
                query(1,i);
            }
        }
        cout<<"!";
        for(int i=2;i<=n;i++){
            cout<<' '<<fa[i]<<' '<<i;
        }
        cout<<endl;
    }
    return 0;
}

D. Longest Max Min Subsequence

题目

You are given an integer sequence a1,a2,…,an. Let S be the set of all possible non-empty subsequences of a without duplicate elements. Your goal is to find the longest sequence in S. If there are multiple of them, find the one that minimizes lexicographical order after multiplying terms at odd positions by −1.

For example, given a=[3,2,3,1], S={[1],[2],[3],[2,1],[2,3],[3,1],[3,2],[2,3,1],[3,2,1]}. Then [2,3,1] and [3,2,1] would be the longest, and [3,2,1] would be the answer since [−3,2,−1] is lexicographically smaller than [−2,3,−1].

A sequence c is a subsequence of a sequence dd ifcc can be obtained from dd by the deletion of several (possibly, zero or all) elements.

A sequence c is lexicographically smaller than a sequence d if and only if one of the following holds:

  • c is a prefix of d, but c≠d;
  • in the first position where c and d differ, the sequence c has a smaller element than the corresponding element in d.

思路

奇数位置应该越大越好,偶数位置应该越小越好,并且越前面优先级越高,例如[4,3]比[3,2]好

用一个数组cnt来存每个值出现的数量,从前往后遍历,每次cnt[a[i]]–,在判断的时候就可以知道某个值在i后面是否还存在,如果该值的cnt=0,说明后面不存在该值,那么就不能删除。

每次遍历到的新的数:

  • 先判断是否已经存在,若存在则跳过
  • 判断当前序列长度
    • 如果序列长度=0,直接存入序列
    • 如果序列长度=1
      • 如果当前v[0]的cnt值不为0,说明后面还有这个数,则与当前值进行比较,如果当前值更大,则将其修改成当前值;否则在后面插入当前值
      • 如果cnt值为0,说明后面没有这个数了,为了满足题目要求最长的不能将其修改,只能在序列后面插入当前值
    • 如果序列长度>1
      • 如果序列长度为奇数,则倒数第一个数应该越大越好,倒数第二个数应该越小越好,由于越前面优先级越高,因此当前值先和倒数第二个数进行比较,如果当前值更小并且倒数第一个数和倒数第二个数的cnt值都不为0,则把最后两个数都删掉;如果不满足前两个当中的任一条件,将当前值与倒数第一的数进行比较,如果当前值更大,并且倒数一个数的cnt值不为0,则删除最后一个数。
      • 如果序列长度为偶数,则倒数第一个数应该越小越好,倒数第二个数应该越大越好,判断条件与以上相反。
    • 一直循环判断2、3,直到不满足其中的任一项条件,则退出循环,在序列最后插入当前值

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+5;
int a[N];
bool vis[N];
vector<int>v;
int cnt[N];
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            vis[i]=false;
            cin>>a[i];
            cnt[a[i]]++;
        }
        v.clear();
        for(int i=1;i<=n;i++){
            cnt[a[i]]--;
            if(vis[a[i]])continue;
            while(!v.empty()){
                if(v.size()>1){
                    int d1=v[v.size()-1],d2=v[v.size()-2];
                    if(v.size()%2){
                        if(d2>a[i]&&cnt[d2]&&cnt[d1]){
                            vis[d2]=false;
                            vis[d1]=false;
                            v.pop_back();
                            v.pop_back();
                        }else if(d1<a[i]&&cnt[d1]){
                            vis[d1]=false;
                            v.pop_back();
                        }else break;
                    }else{
                        if(d2<a[i]&&cnt[d2]&&cnt[d1]){
                            vis[d2]=false;
                            vis[d1]=false;
                            v.pop_back();
                            v.pop_back();
                        }else if(d1>a[i]&&cnt[d1]){
                            vis[d1]=false;
                            v.pop_back();
                        }else break;
                    }
                }else if(v.size()){
                    if(v[0]<a[i]&&cnt[v[0]]){
                        vis[v[0]]=false;
                        v.pop_back();
                    }else break;
                }else break;
            }
            vis[a[i]]=true;
            v.push_back(a[i]);
        }
        cout<<v.size()<<'\n';
        for(int i=0;i<v.size();i++)cout<<v[i]<<("%c",i==v.size()-1?'\n':' ');
    }
    return 0;
}
抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CodeforcesCodeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值