IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces Round #789 (Div. 2) -> 正文阅读

[数据结构与算法]Codeforces Round #789 (Div. 2)

CF系列题解


题目

A. Tokitsukaze and All Zero Sequence

原题链接

A. Tokitsukaze and All Zero Sequence

题意

给定一个序列,可以进行如下操作:

  1. 将两个不同的数 a i , b i a_i,b_i ai?,bi? 变为 他们当中的最小值。
  2. 对于两个相同的数,我们可以将其中一个变为 0 0 0

问将所有数变为 0 0 0 所需要的最少操作次数。

题解

思路

分类讨论:

  1. 当序列中存在 0 0 0,我们可以依次将所有的非零数通过操作1转化为 0 0 0,答案即为非零数的数量。
  2. 若不存在 0 0 0,我们看其中是否有相同的数,若存在相同的数,我们可以将其中一个变为 0 0 0,再把其他数进行思路1,答案即为 n n n
  3. 若不存在相同数,我们可以先把两个数变相同,之后进行思路2,答案即为 n + 1 n+1 n+1

实现上用了排序。

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve()
{
    int n;
    cin >> n;
    
    vector<int> a(n);
    for (int i = 0; i < n; i ++ ) cin >> a[i];

    sort(a.begin(), a.end());

    if (a[0] == 0) {
        int i = 0;
        while (i < n && a[i] == 0) i ++ ;
        cout << n - i << "\n";
    } else {
        bool flag = false;
        for (int i = 0; i < n - 1; i ++ ) {
            if (a[i] == a[i + 1]) {
                flag = true;
                break;
            }
        }
        if (flag) {
            cout << n << "\n";
        } else {
            cout << n + 1 << "\n";
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;

    while (T -- ) {
        solve();
    }

    return 0;
}

B1. Tokitsukaze and Good 01-String (easy version)

原题链接

B1. Tokitsukaze and Good 01-String (easy version)

题意

给定一个 01 字符串,倘若每个连续的相同(即全为 0 或全为 1 )的段其长度为偶数,我们则认为其是好的。问将一个字符串变好需要的最少操作次数。

题解

思路

由于要求每段长度是偶数,那么(下标从 0 0 0 开始)应该满足 s 0 = s 1 , s 2 = s 3 , . . . s_0=s_1,s_2=s_3,... s0?=s1?,s2?=s3?,...,对于不满足的情况我们需要改变其中一个,因此 ans++

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve()
{
    int n;
    cin >> n;

    string s;
    cin >> s;

    int ans = 0;
    for (int i = 0; i + 1 < n; i += 2) {
        if (s[i] != s[i + 1]) {
            ans ++ ;
        }
    }

    cout << ans << "\n";
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;

    while (T -- ) {
        solve();
    }

    return 0;
}

B2. Tokitsukaze and Good 01-String (hard version)

原题链接

B2. Tokitsukaze and Good 01-String (hard version)

题意

上一题的扩展,在满足最小操作次数的同时要使得段数尽可能少,问操作次数和最小的段数。

题解

思路

比赛又写了一大坨代码,回头理一理思路再写。

代码

#include <bits/stdc++.h>

using namespace std;

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    
    int ans0 = 0, res0 = 0;
    bool flag = false;
 
    vector<int> id(n / 2);
 
    for (int i = 0; i < s.size(); i ++ ) {
        if(i == 0) {
            if(s[i] == '0') flag = true;
            res0 ++;
        } else {
            if(flag == true) {
                if(s[i] == '1' && (res0 & 1)) {
                    s[i] = '0';
                    ans0 ++;
                    res0 ++;
                    id[i /2] = 2;
                } else if(s[i] == '1' && res0 % 2 == 0) {
                    flag = false;
                    res0 = 1;
                } else {
                    res0 ++;
                }
            } else if(flag == false) {
                if(s[i] == '0' && (res0 & 1)) {
                    s[i] = '1';
                    ans0 ++;
                    res0 ++;
                    id[i / 2] = 2;
                } else if(s[i] == '0' && res0 % 2 == 0) {
                    flag = true;
                    res0 = 1;
                } else {
                    res0 ++;
                }
            }
        }
 
    }
    n = id.size();
    for (int i = 0; i < s.size(); i += 2)  {
        if (id[i / 2] != 2) {
            if (s[i] == '1') id[i / 2] = 1;
            else id[i / 2] = 0;
        }
    }
    int la = -1, res = 1, res1 = 1, res2 = 1;
 
    if(id[0] == 2) {
        id[0] = 1;
        la = 1;
        for(int i = 1; i < n; i ++ ) {
            if(id[i] == 2 || id[i] == la) {
                continue;
            } else {
                la = id[i];
                res1 ++;
            }
        }
        id[0] = 0;
        la = 0;
        for(int i = 1; i < n; i ++ ) {
            if(id[i] == 2 || id[i] == la) {
                continue;
            } else {
                la = id[i];
                res2 ++;
            }
        }
        res = min(res1, res2);
    } else {
        for(int i = 0; i < n; i ++ ) {
            if(la == -1) {
                la = id[i];
                continue;
            } else  {
                if(id[i] == 2 || id[i] == la) {
                    continue;
                } else {
                    la = id[i];
                    res ++;
                }
            }
        }
    }
    cout << ans0 << ' ' << res << "\n";
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;

    while (T -- ) {
        solve();
    }

    return 0;
}

C. Tokitsukaze and Strange Inequality

原题链接

C. Tokitsukaze and Strange Inequality

题意

给定排列 p p p,求满足 p a < p c , p b > p d p_a<p_c,p_b>p_d pa?<pc?,pb?>pd? 的四元组 [ a , b , c , d ] ( 1 ≤ a < b < c < d ≤ n ) [a,b,c,d] (1≤a<b<c<d≤n) [a,b,c,d](1a<b<c<dn) 的个数。

题解

思路

由数据范围可知复杂度 O ( n 2 ) O(n^2) O(n2),因此肯定是枚举,我们可以枚举 b , c b, c b,c a a a 即为 b b b 的左边比 c c c 小的数, d d d 即为 c c c 的右边比 b b b 小的数,然后就发现很像树状数组求逆序对啊!!!

考虑一下复杂度, l o g ( 5000 ) log(5000) log(5000) 也就是个常数,而且1.5s时限,加上cf神机,虽然好像时间有点紧,但应该能过。

(带火们好像大多用的是前缀和呜呜呜,太菜了想不到)

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

template <typename T> 
struct Fenwick {
    const int n;
    vector<T> tr;
    Fenwick(int n) : n(n), tr(n) {}
    int lowbit(int x) {
        return x & -x;
    }
    void add(int x, T v) {
        for (int i = x; i < n; i += lowbit(i)) tr[i] += v;
    }
    T query(int x) { 
        T res = 0;
        for (int i = x; i; i -= lowbit(i)) res += tr[i];
        return res;
    }
    T rangeSum(int l, int r) { 
        return query(r) - query(l - 1);
    }
};


void solve()
{
    int n;
    cin >> n;

    vector<int> a(n + 1);
    for (int i = 1; i <= n; i ++ ) cin >> a[i];

    Fenwick<int> fen1(n + 1), fen2(n + 1);
    i64 ans = 0;
    for (int b = 2; b <= n - 2; b ++ ) {
        fen1.add(a[b - 1], 1);
        for (int c = n - 1; c > b; c -- ) {
            fen2.add(a[c + 1], 1);
            ans += fen2.query(a[b] - 1) * fen1.query(a[c] - 1);
        }
        for (int c = n - 1; c > b; c -- ) fen2.add(a[c + 1], -1); // 注意还原
    }

    cout << ans << "\n";
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;

    while (T -- ) {
        solve();
    }

    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:08:32  更:2022-05-10 12:12:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年10日历 -2024/10/24 14:21:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码