Codeforces Round #669 (Div. 2) A

题目链接


A. Ahahahahahahahaha

题意:

给定长度为 (n)(0, 1) 数组,(n) 为偶数,你最多可以删去 (frac{n}{2}) 个数,使得结果数组的奇数位和等于偶数位和,输出结果数组。

思路:

计算出 (0)(1) 的个数,谁多就输出谁。

注:(1) 多的情况要判断奇偶。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-08 22:22:23
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-08 22:52:09
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e3 + 10;

int a[N];

int main(){

    int t; cin >> t;
    while(t --){
        int n; cin >> n;
        for(int i = 1; i <= n; i ++) scanf("%d", a + i);
        int x = n >> 1;
        int one = 0, zero = 0;
        for(int i = 1; i <= n; i ++)
            if(a[i] == 1) one ++;
            else zero ++;
        if(one > x){
            if(one & 1) one --;
            cout << one << endl;
            for(int i = 1; i <= one; i ++) printf("1 ");
            puts("");
        } else{
            cout << zero << endl;
            for(int i = 1; i <= zero; i ++) printf("0 ");
            puts("");
        }
        
    }
    
    return 0;
}


B. Big Vova

题意:

给定一个序列 (a),序列 (b)(a) 的一个排列,定义 (c_i = gcd(b_1,...,b_i))

要求求得的 (c) 的字典序最大,求序列 (b)

思路:

看数据范围就可以知道直接暴力即可。

首先很明显的是 (b_1 = max(a_1,a_2,...,a_n)),根据这个找下去即可。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-08 22:59:37
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-08 23:24:08
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e3 + 10;

int a[N], b[N];

map<int, int> mp;

int main(){

    int t; cin >> t;
    while(t --){
        int n; cin >> n;
        
        for(int i = 1; i <= n; i ++) scanf("%d", a + i);
        for(int i = 1; i <= n; i ++) mp[a[i]] ++;
        b[1] = *max_element(a + 1, a + n + 1);
        
        int idx = 1;
        int x = b[1];
        mp[b[1]]--;
        while(idx < n){
            int tmp = 1, val;
            for(int i = 1; i <= n; i ++){
                if(mp[a[i]]){
                    if(gcd(x, a[i]) > tmp){
                        tmp = gcd(x, a[i]);
                        val = a[i];
                    }
                }
            }
            if(tmp == 1) break;
            b[++idx] = val;
            mp[val] --;
            x = tmp;
        }

        if(idx < n){
            for(int i = 1; i <= n; i ++){
                if(mp[a[i]]) b[++idx] = a[i];
            }
        }

        
        for(int i = 1; i <= n; i ++) printf("%d ", b[i]);
        puts("");

        mp.clear();
    }
    return 0;
}


C. Chocolate Bunny

题意:

交互题。

求一个未知的全排列 (a)

可以询问 (2 imes n) 次,每次给出两个不同的索引 (i)(j),会返回 (a_i \% a_j) 的值。

思路:

询问 (i, j),我们假设 (a_i < a_j)

显然 (a_i \% a_j = x = a_i)

再询问 (j, i):

显然 (a_j \% a_i = y < a_i)

那么我们显然 (a_i = max(x, y))

每询问两次可以确定一个位置的值,符合要求。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-08 23:25:35
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-08 23:45:28
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e4 + 10;

int arr[N];

int main(){

    int n; cin >> n;

    if(n == 1) puts("! 1");
    else{
        map<int, int> mp;
        int x = 1;
        int a, b;
        for(int i = 2; i <= n; i ++){
            cout << "? " << x << " " << i << endl;
            cin >> a;
            cout << "? " << i << " " << x << endl;
            cin >> b;
            if(a < b){
                arr[i] = b;
                mp[b] = 1;
            } else{
                arr[x] = a;
                mp[a] = 1;
                x = i;
            }
        }
        for(int i = 1; i <= n; i ++){
            if(mp[i] == 1) continue;
            arr[x] = i;
            break;
        }
        cout << "!";
        for(int i = 1; i <= n; i ++) cout << " " << arr[i];
        puts("");
    }
    
    return 0;
}


D. Discrete Centrifugal Jumps

题意:

(n) 个柱子,第 (i) 个柱子的高度为 (h_i),你满足以下条件之一就可以从 (i) 跳到 (j)

  • (j = i + 1)
  • (max(h_{i+1},...,h_{j-1}) < min(h_i, h_j))
  • (max(h_i, h_j) < min(h_{i+1},...,h_{j-1}))

问从第一个柱子跳到第 (n) 个柱子的最小步数?

思路:

考虑线性 (dp),设 (f[i]):跳到第 (i) 个柱子的最小步数

转移方程:(f[j] = min(f[j], f[i] + 1))(如果 (i) 可以跳到 (j) )。

第一种情况不做考虑,此时我们只考虑第二种情况,第三种类似。

对于 (i) 来说,(j) 就是大于等于他,且离他最近的那个柱子((i < j)),那么此时 (i) 可以跳到 (j),显然这个性质可以单调栈来解决。

不理解代码的可以用这组样例来理解第二种情况:(4,3, 2, 1, 5).

注:

  • 单调递增栈:从栈顶到栈底递增
  • 单调递减栈:从栈顶到栈底递减
代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-09 15:10:43
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-09 15:37:44
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 3e5 + 10;

int h[N], f[N];

stack<int> in, de;

int main(){

    int n; cin >> n;

    memset(f, INF, sizeof f);
    f[1] = 0;

    auto update = [&](stack<int> &s, int idx){
        if(!s.empty()){
            f[idx] = min(f[idx], f[s.top()] + 1);
            if(h[s.top()] == h[idx]) s.pop();
        }
        s.push(idx);
    };

    for(int i = 1; i <= n; i ++){
        scanf("%d", h + i);
        while(!de.empty() && h[i] < h[de.top()]){ // 单调递减栈 对应第三种情况
            f[i] = min(f[i], f[de.top()] + 1);
            de.pop();
        }
        update(de, i);
        while(!in.empty() && h[i] > h[in.top()]){ // 单调递增栈 对应第二种情况
            f[i] = min(f[i], f[in.top()] + 1);
            in.pop();
        }
        update(in, i);
    }

    cout << f[n] << endl;
    
    return 0;
}
原文地址:https://www.cnblogs.com/nonameless/p/13636688.html