首页 > 其他分享 >Codeforces Round 967 (Div. 2)

Codeforces Round 967 (Div. 2)

时间:2024-08-27 17:37:24浏览次数:5  
标签:967 int void 元素 Codeforces mid mp Div 节点

题目链接:Codeforces Round 967 (Div. 2) - Codeforces

总结:B题没测试就交wa一发,C题一直没想到怎么回溯,哎。

A. Make All Equal

tag:签到

Solution:找到相同元素的最大值,将其它所有元素删去。

void solve(){
    cin >> n;
    vector<int> a(n);
    map<int, int> mp;
    int ans = 0;
    for (int i = 0; i < n; i ++){
        cin >> a[i];
        mp[a[i]] ++;
        ans = max(ans, mp[a[i]]);
    }
    cout << n - ans << endl;
}

B. Generate Permutation

tag:构造

Solution:对于一个数\(i\),我们发现如果\(i - 1\)在它左边,则第二台打字机执行一次回车;如果在它右边,则第一台打字机执行一次回车。那么我们构造一个\(a_4a_2a_1a_3a_5\)。同时发现\(n\)是偶数,一定不行。

Competing:一下就猜中了,写完代码后没测试,wa一发。

void solve(){
    cin >> n;
    if (n % 2 == 0){
        cout << "-1\n";
    }
    else{
        vector<int> a(n);
        int t = n - 1;
        for (int i = 1; t; i ++){
            a[i] = t;
            t -= 2;
        }
        t = n;
        for (int i = n; t >= 1; i --){
            a[i] = t;
            t -= 2;
        }
        for (int i = 1; i <= n; i ++){
            cout << a[i] << " \n"[i == n];
        }
    }
}

C. Guess The Tree

tag:交互 + dfs

Description:给定一个\(n\)个节点的数,每次询问输出? a b,会返回一个节点\(x\),使|d(x - a) - d(x - b)|最小。\(d(x, y)\)表示\(x\)到\(y\)的距离。如果有多个这样的节点,会返回使d(x, a)最小的节点。用最多\(15n\)次查询,得出树的结构。

Solution:分析每次询问得到的结果发现每次都会给出\(a, b\)路径上的中点\(mid\),那么我们继续询问\(a, mid\)与\(mid, b\),直到\(mid == a || mid == b\)。

  • 需要记录每个节点的父节点,避免重复询问。
  • 对于一棵树,我们可以假设任意一个节点为根

Competing:想到应该用\(mid\)继续往下问,但是没想到使用\(dfs\),导致不知道如何回溯。

int query(int a, int b){
    cout << "? " << a << " " << b << endl;
    int x;
    cin >> x;
    return x;
}
 
void dfs(int a, int b){  // a是父节点
    if (fa[a] && fa[b])
        return;
    int t = query(a, b);
    if (a == t || t == b){
        fa[b] = a;
        ans.push_back({a, b});
        return;
    }
    else{
        dfs(a, t);
        dfs(t, b);
    }
}
 
void solve(){
    cin >> n;
    ans.clear();
    for (int i = 0; i <= n; i ++){
        fa[i] = 0;
    }
    fa[1] = 1;
    while (ans.size() < n - 1){
        for (int i = 2; i <= n; i ++){
            if (fa[i] == 0){
                dfs(1, i);
            }
        }
    }
    cout << "! ";
    for (int i = 0; i < ans.size(); i ++){
        cout << ans[i].fi << " " << ans[i].se << " ";
    }
    cout << endl;
}

D. Longest Max Min Subsequence

tag:思维 + 贪心 + 单调队列优化

Description:给定一个整数序列\(a\),\(s\)是\(a\)的所有非空子序列的集合,要找到一个最长的\(s\),如果有多个序列,则找出奇数位乘\(-1\),之后字典序最小的序列。

  • n <= 3e5

Solution:我们首先可以确定哪些值是必须要选的。我们要保证能选出最长的序列,就需要记录每个值最后出现的位置,在最后出现的位置最小的元素之前我们可以任意选择,而不能先选在该元素之后的其他元素。

  • 一个可选的区间内,对于奇数位我们选择值最大的元素,对于偶数位我们选择值最小的元素。如果我们每次暴力寻找,时间复杂度为\(O(n ^2)\),考虑使用单调队列优化。
void solve(){
    cin >> n;
    vector<int> a(n + 1);
    unordered_map<int, int> mp;
    set<int> st;
    for (int i = 1; i <= n; i ++){
        cin >> a[i];
        mp[a[i]] = i;
    }
 
    for (auto [x, y] : mp){  // 记录每个元素最后出现的位置
        st.insert(y);
    }
    int sz = mp.size();
    cout << sz << endl;
    int s = 1;
    int c = 0;
    
    priority_queue<pii, vector<pii>, greater<pii>> smi;  // 值从小到大,序号从小到大
    priority_queue<pii, vector<pii>, greater<pii>> sma;  // 值从大到下,序号从小到大
 
    int tt = 0;
    while (c < sz){
        int et = *(st.begin()); // 当前最前面最后出现的元素的位置
        int res, idx;
        for (int i = s; i <= et; i ++){
            if (mp[a[i]] != 0){ // 等于0说明选过了
                smi.push({a[i], i});
                sma.push({-a[i], i});
            }
        }
 
        if ((c + 1) & 1){  // 选最大值
            auto [x, y] = sma.top();
            res = x, idx = y;
        }
        else{ // 选最小值
            auto [x, y] = smi.top();
            res = x, idx = y;
        }
        cout << a[idx] << " ";
 
        st.erase(mp[a[idx]]);  // 删除选择点的下标
        mp[a[idx]] = 0;
        s = et + 1;
        c ++;
        while (sma.size()){ // 删除选择过的元素或者下标小于当前值的元素
            auto [x, y] = sma.top();
            if (res > 0)
                res = -res;
            if (!mp[-x] || y <= idx)
                sma.pop();
            else
                break;
        }
        while (smi.size()){
            auto [x, y] = smi.top();
            if (res < 0)
                res = -res;
            if (!mp[x] || y <= idx)
                smi.pop();
            else
                break;
        }
    }
    cout << endl;
}

标签:967,int,void,元素,Codeforces,mid,mp,Div,节点
From: https://www.cnblogs.com/Sakura17/p/18383211

相关文章

  • Codeforces Round 962 (Div. 3)
    A.Legs若只判断题,根据模4意义下分类即可。B.Scale模拟题,缩小同值矩阵即可。C.Sort对每个字母求前缀数量和,答案就是两端点的差。constintN=2e5+5;intT,n,q;chara[N],b[N];intc[N][26],d[N][26];signedmain(void){ for(read(T);T;T--){ read(......
  • Codeforces Round 968 (Div. 2)
    A.TurtleandGoodStrings题意:确定是否存在一种方案使得\(s=t_1+t_2+\cdots+t_m\),满足\(m>1\)且任意\(i<j\),\(t_i\)的第一个字母不等于\(t_j\)的最后一个字母。\(s_1\)和\(s_n\)一定不属于一个子串,因此\(s_1\nes_n\)是条件非法的必要条件。那么反......
  • Codeforces Round 968 (Div. 2)
    A.TurtleandGoodStrings思路:题意大致为把一个字符串分成若干段,要求每两段,前一段的首字符不能等于后的一段的尾字符,给你一个字符串,能不能构造出合法方案。观察到,分的段数越小,越有助于我们判断。所以,不妨分成两段,问题转化为判断首尾字符是否相等。代码:#include<bits/stdc++.......
  • [ARC182C] Sum of Number of Divisors of Product 题解
    题目链接点击打开链接题目解法我怎么不会分治/fn首先把\(x\)分解成\(\prodp_i^{x_i}(0\lei\le5)\)的形式,正因数个数为\(\prod(x_i+1)\)有一个很牛的想法是:合并两个\(x_i\)序列(假设一个叫\(x_0,...,x_5\),另一个叫\(y_0,...,y_5\))先不考虑后面的\(+1\)(可以最后......
  • Codeforces Round 968 (Div. 2)
    良心出题人给了中文题解!!!A.TurtleandGoodStrings长度为\(n\)的字符串至少分成两段,使\(\foralli<j\),第\(i\)段的首字符不等于第\(j\)段的尾字符第一个字符一定作为首字符,最后一个字符一定作为尾字符,只要判断这两个字符是否相等即可相等的话一定无解,不相等一定有......
  • EPIC Institute of Technology Round August 2024 (Div. 1 + Div. 2)
    Preface两个礼拜前打的比赛拖到现在才写博客,我只能说也是个神人了这场其实D2很快就想到做法了,但自己把自己给否了,后面不管了实现了一发交上去发现过了然后这天由于12点左右室友就关灯睡觉了,我写完D2后看了眼E没仔细想就睡觉去了,后面发现E其实很trivialA.Distance......
  • Codeforces Round #900 (Div. 3)
    三年之后第一次打比赛,用小号打了场\(Div.3\),居然没有AK,感觉实力退步到小学了。A.HowMuchDoesDaytonaCost?若只判断题,只要判断\(\{a_n\}\)中是否存在\(k\)即可。B.AleksaandStack构造方法不唯一,我直接输出奇数列,显然正确。C.VasilijeinCacak若只判断题......
  • Codeforces Round 967 (Div. 2) - C
    题意概述这是一个交互题。有一棵有\(n\)个节点的树,节点编号从\(1\)到\(n\),并要求你使用以下类型的查询来猜测它:"?ab"会告诉你哪个节点\(x\)在点\(a\)和\(b\)之间(\(|d(a,x)-d(b,x)|\)的值最小),其中\(d(x,y)\)是节点\(x\)和\(y\)之间的距离。如果存在不......
  • CodeForces - 1353D Constructing the Array
    CodeForces-1353D这道题也可能比较简单,主要是要想到优先队列要怎么使用,这一点如果用递归会写不了但是因为对优先队列不太熟悉,只有被提示可以用优先队列才想到要怎么用,还是很重要的STL注意运算符的重构应该反着来写其他的思维很朴素,运算符的重构就是,先比较长度,优先用长度长......
  • CodeForces-431C k-Tree
    感觉这个题的dp还是有点思维的,可能就是我现在能做到的题目的天花板级别的了,dp还是要点灵感感觉,以下是代码,可能要写题解要过好久,先水着include<bits/stdc++.h>defineintlonglongdefineendl'\n'usingnamespacestd;constintmod=1000000007;intn,k,d;intdp[200][2]=......