AtCoder Beginner Contest 240 题解

A - Edge Checker

题目大意:

给个1 - 10 数字围成一个圈,给你两个数问你是否相邻

int main (){
    IOS
    int a, b; cin >> a >> b;
    if (abs (a - b) == 1){
        cout << "Yes" << endl;
    }
    else if (a == 10 && b == 1 || a == 1 && b == 10) {
        cout << "Yes" << endl;
    }
    else cout << "No" << endl;
}

B - Count Distinct Integers

题目大意;

给一个数组,问你出现了多少不同的数字。(丢 set 里就行)

int main (){
    IOS
    set <int> s;
    int n; cin >> n;
    for (int i = 1 ; i <= n ; i ++){
        int x; cin >> x;
        s.insert(x);
    }
    cout << s.size () << endl;
    return 0;
}

C - Jumping Takahashi

题目大意:

给定目的点 x, 跳跃 n 次,每次可以从 a, b 中选择一个数跳跃一定的距离。问从起点 0 开始,能否恰好跳跃到 x 点。

分析:

暴力枚举每一次选 a 或者 b, 时间复杂度 O(2n) , 显然不行。考虑用 dp[i][j]去表示前 i 次跳跃后,是否能到达 j 点。

时间复杂度 O(nx) ,可以用滚动优化掉一维,但是懒得搞了qwq。

int f[105][10005];
int main (){
    IOS
    int n, x; cin >> n >> x;
    f[0][0] = 1;
    for (int i = 1 ; i <= n ; i ++){
        int a, b; cin >> a >> b;
        for (int j = 0 ; j <= 10000 - a ; j ++){
            if (f[i - 1][j])
            f[i][j + a] = f[i - 1][j];       
        }
        for (int j = 0 ; j <= 10000 - b ; j ++){
            if (f[i - 1][j])
            f[i][j + b] = f[i - 1][j];       
        }
    }
    if (f[n][x]){
        cout << "Yes" << endl;
    }
    else cout << "No" << endl;
    return 0;
}

D - Strange Balls

题目大意:

类似于 “祖玛” 的游戏,一个一个往桶里添加小球,当 小球的编号与连续个数相同时,这部分小球会被消掉。求出每次添加小球后桶中小球个数。

分析:

用两个栈去维护即可,一个栈维护个数,一个栈维护桶内小球的情况,然后模拟输出即可。(一开始以为连续球必然会消去,wa了一发)

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
using namespace std;
const int N=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;
int a[N];
int main (){
    IOS
    int t; cin >> t;
    stack <int> s, c;
    int now = 0, cnt = 0;
    while (t --){
        int n; cin >> n;
        if (s.empty()){
            s.push(n);
            now = n; cnt ++;
        }
        else {
            if (s.top () == n){
                if (cnt == n - 1){
                    while (s.size () > 0 && s.top () == n) s.pop();
                    if (s.empty()) now = 0, cnt = 0;
                    else{
                        if (c.empty()) cnt = 0;
                        else {
                            cnt = c.top(); c.pop();
                        }
                        n = s.top ();
                    }
                }
                else {
                    s.push(n);
                    cnt ++;
                }
            }
            else {
                s.push(n);
                c.push(cnt);
                now = n, cnt = 1;
            }
        }
        cout << s.size () << endl;
    }
    return 0;
}

E - Ranges on Tree

题目大意:

给一颗根节点为 1 的树,每个节点有一个集合 Si , 表示以该节点为根节点的子树包含的节点数。要求给树上的所有节点,分配一个区间,使得节点之间的区间关系和 Si 之间的关系一致。输出分配情况,同时使得所有区间的最右端最小。(用尽可能小的数去分配)

例如: 如果节点2 和节点 3 的子树没有交集,那么为这两个节点分配的区间的交集也应当为空集。如果节点 1 的子树包含节点 2 的子树,那么区间 1 也应当包含 区间 2。

分析:

显然可以看出,根节点 1 包含所有其他节点, 那么根节点的区间一定是最大的。又可以看出,每个叶子节点一定是相互独立的,所以要为每个叶子节点分配一个值。所以,根节点的长度为树中叶子节点的个数。按每颗子树的叶子节点数分配区间即可。

题目不难想,题意有点难读,我读了n个错误题意 ,比赛中实现得比较复杂,第一遍 dfs 求 每棵树的叶子节点个数,第二遍 dfs 赋值。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
using namespace std;
const int N=3e5+7;
const double eps=1e-6;
const int mod=1e9+7;
vector <int> a[N];
int cnt = 0;
bool st[N];
int d[N];
struct node{
    int l, r;
};
node ans[N];
int dfs (int u){
    bool flag = 0;
    for (auto i : a[u]){
        if (!st[i]){
            flag = 1;
            st[i] = 1;
            d[u] += dfs(i);
            st[i] = 0;
        }
    }
    if (flag)
        return d[u];
    d[u] = 1;
    return d[u];
}
void dfs2 (int u, int l){
    int loc = l;
    ans[u].l = l, ans[u].r = l + d[u] - 1;
    for (auto i : a[u]){
        if (!st[i]){
            st[i] = 1;
            dfs2 (i, loc);
            loc += d[i];
            st[i] = 0;
        }
    }
}
int main (){
    IOS
    int n; cin >> n;
    for (int i = 1 ; i < n ; i ++){
        int u, v; cin >> u >> v;
        a[u].push_back(v);
        a[v].push_back(u);
    }
    st[1] = 1;
    dfs(1);
    memset (st, 0, sizeof st);
    st[1] = 1;
    dfs2 (1, 1);
    for (int i = 1 ; i <= n ; i ++){
        cout << ans[i].l << ' ' << ans[i].r << endl;
    }
    return 0;
}

F - Sum Sum Max

题目大意:

给定一个数组 C,其前缀和数组 为 B , B的前缀和数组为 C,求 A 中的最大值。C数组长度为 m (< 1e9), 给出方式是 n 行读入,每行读入为 x, y。表示 C 数组中有连续的 y 个 x。

分析:

从数据范围来看, 此题暴力的复杂度是 m,行不通。试着去摸几组样例,会发现,b 是 由多个等差数列组成的。反映到坐标轴上会发现,b是由一段一段斜率不同的一次函数构成的。如下图所示

不难发现,最大值出现在两端,或者是 B 与 x = 0 的交点处(当然实际情况是离散的整数点),取 大于 0 的最小值即可。

实际写的时候,我每一段的右端点和 0 点都更新了答案。

#include<bits/stdc++.h>
#define int long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define Equ(a,b) (fabs((a)-(b))<eps)
#define More(a,b) (((a)-(b))>(eps))
#define x first
#define y second
#define endl '\n'
using namespace std;
const int N=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;
int x[N], y[N];
signed main (){
    IOS
    int t; cin >> t;
    while (t --){
        int n, m; cin >> n >> m;
        for (int i = 1 ; i <= n ; i ++) cin >> x[i] >> y[i];
        int ans = x[1], now = 0, sum = 0;
        for (int i = 1 ; i <= n ; i ++){
            int l = now + x[i], r = now + x[i] * y[i];
            ans = max (sum + l, ans);
            if (x[i] < 0 && r < 0 && l > 0){
                int step = abs (x[i]);
                int tr = l - l / step * step;
                ans = max (sum + (tr + l) * ((tr - l) / x[i] + 1) / 2, ans);
            }
            sum += (l + r) * y[i] / 2;      
            now = r;
            ans = max (sum, ans);
        }
        cout << ans << endl;
    }
    return 0;
}

其实本题应该是可以写出来的,赛中较为可惜。

posted @   sweet_guagua  阅读(501)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示