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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> AtCoder ABC237题解 -> 正文阅读

[数据结构与算法]AtCoder ABC237题解

ABC237

对应地址,https://atcoder.jp/contests/abc237/tasks

A - Not Overflow

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_a

题目要求

给定一个整数 X X X,判断 X X X 是否在 int \text{int} int 范围内。

简易题解

签到题。
我们可以使用 C++ 的 INT_MAX 和 INT_MIN。如果不知道这两个常数,可以自己定义。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    LL n;
    cin>>n;
    if (n>=INT_MIN && n<=INT_MAX){
        cout<<"Yes\n";
    }else{
        cout<<"No\n";
    }
    return 0;
}

时间复杂度

O ( 1 ) O(1) O(1)

空间复杂度

O ( 1 ) O(1) O(1)

B - Matrix Transposition

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_b

题目要求

输出 H × W H \times W H×W 矩阵的转秩矩阵。

简单题解

签到题。
本题的难点在于数据太大。根据题目要求
1 ≤ H , W ≤ 1 0 5 1 \leq H,W \leq 10^5 1H,W105
W × H ≤ 1 0 5 W \times H \leq 10^5 W×H105
我们没法直接定义出一个二维数组,因为这样定义,我们必然会得到 MLE \text{MLE} MLE,本题只能用二维 vector \text{vector} vector 来实现。
解决了数据存储问题,代码自然非常简单。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    LL h,w;
    cin>>h>>w;
    vector<vector<LL>> a(h,vector<LL>(w));
    for (auto &x:a){
        for (auto &y:x){
            cin>>y;
        }
    }
    for (LL i=0; i<w; i++){
        for (LL j=0; j<h; j++){
            cout<<a[j][i]<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

时间复杂度

O ( H ? W ) O(H*W) O(H?W)

空间复杂度

O ( H ? W ) O(H*W) O(H?W)

C - kasaka

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_c

题目要求

给一个长度为 n n n 的字符串 s s s,判断能否在开头增加若干(包含 0 0 0)个字符 a a a,使得字符串 s s s 变成回文字符串。

简单题解

我们可以使用双指针来解决这个问题。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin>>s;
    
    LL n=s.size();
    LL l=0, r=n-1;
    LL tl=0, tr=0;
    //定义第一个a
    while (l<n && s[l]=='a') {
        l++;
        tl++;
    }
    //定位最后一个a
    while (r>=0 && s[r]=='a') {
        r--;
        tr++;
    }
    
    if (tr<tl) {
        cout<<"No\n";
        return 0;
    }
    
    while (l<r) {
        if (s[l]==s[r]) {
            l++;
            r--;
        } else {
            break;
        }
    }
    
    if (l<r) {
        cout<<"No\n";
    } else {
        cout<<"Yes\n";
    }
    
    return 0;
}

时间复杂度

O ( n ) O(n) O(n)

空间复杂度

O ( n ) O(n) O(n)

D - LR insertion

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_d

题目要求

给一个字符串 S S S,按照要求将数据 i i i 插入到数列 A A A 中。

简单题解

数据结构题。可以使用双向队列,也可以使用双指针来解决。
通过观察输入样例 2 2 2,我们可以得到如下结论:

  • 碰到 ‘L’,我们从右边(队尾)插入数据。
  • 碰到 ‘R’,我们从左边(队头)插入数据。

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    LL n;
    cin>>n;
    string s;
    cin>>s;
#if 1
    vector<LL> a(n+1,0);
    LL l=0;
    LL r=n;
    for (LL i=0; i<n; i++){
        if (s[i]=='L'){
            a[r]=i;
            r--;
        }else{
            a[l]=i;
            l++;
        }
    }
    a[l]=n;
#else
    deque<LL> a;
    a.push_back(n);
    for (LL i=n-1; i>=0; i--){
        if (s[i]=='L'){
            a.push_back(i);
        }else{
            a.push_front(i);
        }
    }
#endif
    for (const auto &x:a){
        cout<<x<<" ";
    }
    cout<<"\n";
    return 0;
}

时间复杂度

O ( n ) O(n) O(n)

空间复杂度

O ( n ) O(n) O(n)

E - Skiing

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_e

题目要求

给一个无向图,高桥从顶点 1 1 1 出发,他能得到的最大快乐。

简单题解

图论的基础题,思路参考单源最短路问题。基本步骤如下:

  • 建边。
  • 从起点 1 1 1 出发,遍历所有边。并更新距离。
  • 查找所有距离中的最大值。

AC代码

数组版本

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
const int M=2*N;
LL h[N];//头节点
LL dis[N];//距离
LL vis[N];//可见性控制
LL happy[N];//幸福度
//下面数据结构来描述图
LL e[M];
LL ne[M];
LL idx;

void add(LL u, LL v) {
    //建边 u->v
    e[idx]=v;
    ne[idx]=h[u];
    h[u]=idx;
    idx++;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    //初始化
    memset(dis, -0x3f, sizeof dis);
    memset(h, -1, sizeof h);

    LL n,m;//n个顶点,m条边
    cin>>n>>m;
    for (LL i=1; i<=n; i++) {
        cin>>happy[i];
    }
    for (LL i=1; i<=m; i++) {
        LL u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }

    queue<LL> que;
    dis[1]=0;//起点距离为0
    que.push(1);
    while (que.size()) {
        LL x=que.front();
        que.pop();

        vis[x]=false;
        //以x为起点,遍历x的所有边
        for (LL i=h[x]; i!=-1; i=ne[i]) {
            LL y=e[i];//x->y
            LL c=happy[x]-happy[y];//从x->y的幸福度
            if (c<0) {
                c*=2;
            }
            if (dis[y]<dis[x]+c) {
                dis[y]=dis[x]+c;
                if (false==vis[y]) {
                    que.push(y);
                    vis[y]=true;
                }
            }
        }
    }

    //遍历查找最大值
    LL ans=0;
    for (LL i=1; i<=n; i++) {
        ans=max(ans, dis[i]);
    }
    cout<<ans<<"\n";

    return 0;
}

vector版本

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    LL n,m;
    cin>>n>>m;
    vector<vector<LL>> adj(n+1);
    vector<LL> dis(n+1, -9e18);//距离
    vector<bool> vis(n+1, false);//可见性
    vector<LL> happy(n+1);//幸福度
    //读取幸福度
    for (LL i=1; i<=n; i++) {
        cin>>happy[i];
    }
    //读取图
    for (LL i=0; i<m; i++) {
        LL u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    queue<LL> que;
    dis[1]=0;//起点距离为0
    que.push(1);
    while (que.size()) {
        LL x=que.front();
        que.pop();

        vis[x]=false;
        //以x为起点,遍历x的所有边
        for (const auto &y:adj[x]) {
            LL c=happy[x]-happy[y];//从x->y的幸福度
            if (c<0) {
                c*=2;
            }
            if (dis[y]<dis[x]+c) {
                dis[y]=dis[x]+c;
                if (false==vis[y]) {
                    que.push(y);
                    vis[y]=true;
                }
            }
        }
    }

    //遍历查找最大值
    LL ans=0;
    for (LL i=1; i<=n; i++) {
        ans=max(ans, dis[i]);
    }
    cout<<ans<<"\n";

    return 0;
}

P.S.
数组版本时间为 85ms。vector版本时间为 104ms。

时间复杂度

O ( m ) O(m) O(m)

空间复杂度

O ( m ) O(m) O(m)

F - |LIS| = 3

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_f

题目要求

给定整数 n , m n,m n,m,求满足以下所有条件的数列总数。

  • 长度为 n n n
  • 数字是 1 ~ m 1 \sim m 1m 构成。
  • ∣ L I S ∣ = 3 |LIS|=3 LIS=3

简单题解

读完题目,就知道是一个动态规划问题。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;

const LL MOD=998244353;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    LL n,m;
    cin>>n>>m;

    //找出所有位置
    vector<vector<LL>> pos;
    for (LL i=0; i<=m; i++) {
        for (LL j=0; j<=m; j++) {
            for (LL k=0; k<=m; k++) {
                if (i>j || (i==j && i!=m)) {
                    continue;
                }
                if (j>k || (j==k && j!=m)) {
                    continue;
                }
                pos.push_back({i,j,k});
            }
        }
    }

    LL dpn = pos.size();
    vector<PLL> trans;
    for (LL i=0; i<dpn; i++) {
        auto from = pos[i];
        for (LL j=0; j<m; j++) {
            auto tmp = from;
            LL updp = lower_bound(tmp.begin(), tmp.end(), j)-tmp.begin();
            if (updp==3) {
                continue;
            }
            tmp[updp] = j;
            LL to = lower_bound(pos.begin(), pos.end(), tmp)-pos.begin();
            trans.push_back({i, to});
        }
    }

    vector<LL> dp(dpn, 0);
    dp.back()=1;
    for (LL i=0; i<n; i++) {
        vector<LL> tmp(dpn, 0);
        for (const auto &x:trans) {
            tmp[x.second]=(tmp[x.second]+dp[x.first])%MOD;
        }
        swap(dp, tmp);
    }

    //遍历答案
    LL ans=0;
    for (LL i=0; i<dpn; i++) {
        auto st = pos[i];
        if (st.back()!=m) {
            ans=(ans+dp[i])%MOD;
        }
    }
    cout<<ans<<"\n";

    return 0;
}

时间复杂度

O ( m 3 ) O(m^3) O(m3)

空间复杂度

O ( n ) O(n) O(n)

G - Range Sort Query

链接地址

https://atcoder.jp/contests/abc237/tasks/abc237_g

题目要求

给一个 N N N 个数构成的排列,一个整数 X X X
另外 Q Q Q 次查询,一下搞一个升序,一下搞一个降序。
最终的操作结果是什么。

简单题解

使用线段树吧。这么复杂的操作。
麻烦的是,我特么忘记了线段树的实现。
哎,杀人诛心啊。太难过了。让我查查过去的代码。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:51:59  更:2022-02-01 20:52:21 
 
开发: 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/26 18:31:23-

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