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 #529 (Div. 3) A~F题解 -> 正文阅读

[数据结构与算法]Codeforces Round #529 (Div. 3) A~F题解

A. Repeating Cipher

  • 解题思路

    按距离间距索引字符即可。

  • 参考代码

#include<bits/stdc++.h>

using namespace std;

int n;
string s;
int main(){
    cin >> n >> s;
    int idx = 0,cnt = 1;
    while(idx < n){
        cout << s[idx];
        idx += cnt;
        cnt ++;
    }
    cout << endl;
    return 0;
}

B. Array Stabilization

  • 解题思路

    简单贪心,为了减小极差,要么删最大值要么删最小值。

  • 参考代码

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;
int n,a[N];
void solve(){
    sort(a + 1,a + 1 + n);
    //要么删最大值要么删最小值。
    printf("%d\n", min(a[n - 1] - a[1], a[n] - a[2]));
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &a[i]);
    }
    solve();
    return 0;
}

C. Powers Of Two

  • 解题思路

    n n n按二进制位展开,那么展开后的每个二进制数都是 2 2 2的次幂。那么我们又知道对于 2 k , k > 0 2^k,k >0 2k,k>0,其可以转换成 2 2 2 2 k ? 1 2^{k-1} 2k?1,则会使个数加 1 1 1 根据此原理,我们从高往低凑成 k k k 2 2 2的次幂即可。

  • 参考代码

#include<bits/stdc++.h>

using namespace std;

int n,k;
int a[31];
void solve(){
    a[0] = 1;
    for(int i = 1; i < 31; ++ i){
        a[i] = a[i - 1] * 2;
    }
    //我们将n拆成二进制,那么二进制上的每一位都是2的次幂,而每一个不是1的2的次幂又可以拆分成2个2的次幂。通过这种思想去凑k。
    priority_queue<int> pos;
    for(int i = 0; i < 31; ++ i){
        if(n & a[i]){
            pos.push(i);
        }
    }
    //分解操作会使大小+1。如果可行那一定可以达到k。
    while(pos.size() < k && pos.top() > 0){
        int idx = pos.top();
        pos.pop();
        pos.push(idx - 1);
        pos.push(idx - 1);
    }
    if(pos.size() == k){
        cout << "YES" << endl;
        while(!pos.empty()){
            cout << a[(int)pos.top()] << " ";
            pos.pop();
        }
        cout << endl;
    }
    else{
        cout << "NO" << endl;
    }
}
int main(){
    cin >> n >> k;
    solve();
    return 0;
}

D. Circular Dance

  • 解题思路

    首先我们要知道,这实际上就是一个环,所以我们可以任取元素作为队头。而解决这道题目的关键就是确定一个元素的后两个元素的位置,那么可以根据后两个元素之间的关系来确定,因为第二个元素一定在第一个元素的后两个元素中。 这样循环迭代即可得出整个序列。

  • 参考代码

#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;

const int N = 2e5 + 10;
int n;
pair<int,int> a[N];
void solve(){
    //注意,这个相当于一个圈,所以我们可以任取队头。
    //确定队头之后,怎么确定之后的两个元素的顺序呢。
    vector<int> q;//队列q。
    q.push_back(1);
    int x = a[1].x, y = a[1].y;
    bool flag = true;
    //判断x的后两个元素是不是y。
    if(a[x].x == y || a[x].y == y){
        flag = false;
    }
    if(flag){
        swap(x,y);//那么说明x的后一个元素不是y,则y在x前面,我们交换这两个值即可。保证x在前y在后。
    }
    q.push_back(x),q.push_back(y);
    int len = q.size();
    while(len < n){
        int cur = a[x].x;
        if(y == cur){
            //说明cur是第一个元素,而我们要将第二个元素入队。
            cur = a[x].y;
        }
        q.push_back(cur);
        //这样一直迭代后两个元素。
        len ++;
        x = y;
        y = cur;
    }
    for(int i = 0; i < len; ++ i){
        cout << q[i] << " ";
    }
    cout << endl;
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d%d", &a[i].x, &a[i].y);
    }
    solve();
    return 0;
}

E. Almost Regular Bracket Sequence

  • 解题思路

    由于我们只能修改一个位置的括号,所以必然是只存在一对不合法的括号,我们将这个不合法的给找出来。再讨论情况。 那么我们可以利用栈来实现括号匹配,而当匹配完之后栈内必须要两个元素我们才可能实现。那么对于这其中的两个元素,我们需要判断是什么类型的,对于 ) ) )) )) ( ( (( ((我们都是可以是实现的,而 ) ( )( )(无论我们怎么修改都无法配对。

  • 参考代码

#include<bits/stdc++.h>

using namespace std;

int n;
string str;
void solve(){
    //由于我们只能修改一个位置的括号,所以必然是只存在一对不合法的括号,我们将这个不合法的给找出来。再讨论情况。
    stack<int> s;
    for(int i = 0; i < n; ++ i){
        if(str[i] == '('){
            s.push(i);
        }
        else{
            //碰到右括号就进行括号匹配。
            if(!s.empty() && str[s.top()] == '('){
                s.pop();
            }
            else{
                s.push(i);//如果不能匹配就入队。
            }
        }
    }
    //最后栈的大小一定是2个。其他的则不合法。
    int ans = 0;
    if(s.size() == 2){
        int idx2 = s.top();
        s.pop();
        int idx1 = s.top();
        //分析判断。注意按idx1 < idx2,因为我们是按下标顺序入栈的。
        if(str[idx1] == ')'){
            if(str[idx2] == '('){
                //)(当存在这种情况,我们无法修改使得其变为合法,因为进行操作只能对二者其中一个起作用。
                ans = 0;
            }
            else{
                //))当存在这种情况。我们将idx1左边的修改为(即可。
                for(int i = 0; i <= idx1; ++ i){
                    if(str[i] == ')'){
                        ans ++;
                    }
                }
            }
        }
        else{
            //说明是((类型,我们将)右边的修改为)即可。
            for(int i = idx2; i < n; ++ i){
                if(str[i] == '('){
                    ans ++;
                }
            }
        }
    }
    cout << ans << endl;
}
int main(){
    cin >> n >> str;
    solve();
    return 0;
}

F. Make It Connected

  • 解题思路

    最小生成树模板题。特别需要注意的一点就是我们不需要存储 n × ( n ? 1 ) 2 \frac{n\times(n - 1)}{2} 2n×(n?1)?条边,根据贪心原则我们会选取权值较小的边构建 M S T MST MST,所以我们可以对顶点权排序,通过点权最小的点和其他点构建 n ? 1 n-1 n?1条边即可,剩下的即可舍去。既而我们再考虑增添的 m m m条边,将这些边组合排序进行Kruskal算法实现即可。

  • 参考代码

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

typedef long long ll;

int n,m;
struct node{
    int u;
    ll w;
    bool operator < (const node &A){
        return w < A.w;
    }
}nodes[N];
struct edge{
    int u,v;
    ll w;
    bool operator < (const edge &A){
        return w < A.w;
    }
}edges[N << 2];
int tot,father[N];
int find(int x){
    int r = x;
    while(r != father[r])r = father[r];
    int i = x,j;
    while(father[i] != r){
        j = father[i];
        father[i] = r;
        i = j;
    }
    return r;
}
void solve(){
    sort(nodes + 1, nodes + 1 + n);
    for(int i = 2; i <= n; ++ i){
        //如果不适用魔法,而是直接连接的话必然是选择权值较小的,则以最小的与其他n-1个点相连即可。
        edges[++ tot].u = nodes[1].u;
        edges[tot].v = nodes[i].u;
        edges[tot].w = nodes[i].w + nodes[1].w;
    }
    sort(edges + 1, edges + 1 + tot);
    for(int i = 1; i <= n; ++ i)father[i] = i;
    ll ans = 0;
    for(int i = 1; i <= tot; ++ i){
        int fu = find(edges[i].u), fv = find(edges[i].v);
        if(n == 1)break;//当集合只剩一下即连通。
        if(fu != fv){
            father[fu] = fv;
            ans += edges[i].w;
            n --;
        }
    }
    printf("%lld\n", ans);
}
int main(){
    scanf("%d%d", &n ,&m);
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &nodes[i].w);
        nodes[i].u = i;
    }
    for(int i = 1; i <= m; ++ i){
        tot ++;
        scanf("%d%d%lld", &edges[tot].u, &edges[tot].v, &edges[tot].w);
    }
    solve();
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:29:50  更:2021-07-27 16:31:35 
 
开发: 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年11日历 -2024/11/25 17:24:45-

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