0
点赞
收藏
分享

微信扫一扫

2022 04 01学习记录

一叶随风_c94d 2022-04-02 阅读 24
算法c++

AcWing 730. 机器人跳跃问题(二分 or 贪心)

题目链接:https://www.acwing.com/problem/content/732/

Description:

​ 有n个点 要一步一步跳 设起点处初始能量为E 每跳一个点 E += E - q[i]

​ 要求到达终点n并且在跳跃的过程中E >= 0 求最小初始值

Solution:

​ 一看到1e5和单调性最值我就想写二分 简简单单的一个二分就写出来了 样例也过了 但是wa

​ 感觉是爆了int 查看check式子中的公式 x += x - q[i] 感觉如果n=1e5 x = 5e2 那样就是x*2^n

​ 这哪止是爆了int啊 明明就是爆了LL

​ 所以我们不能一直累加 由公式E += E - q[i] 当E>maxH之后 E-q[i]始终为正数 即一定能到达终点

Code:

typedef long long LL;
int q[100010];
int n, mxh;

bool check(LL x)
{
    for(int i = 1; i <= n; i++)
    {
        x += x - q[i];
        if(x >= mxh)    return true;
        if(x < 0) return false;
    }
    return true;
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> q[i], mxh = max(mxh, q[i]);
    
    LL l = 0, r = mxh;
    while(l < r)
    {
        LL mid = l + r >> 1;
        if(check(mid))  r = mid;
        else l = mid + 1;
    }
    cout << r << endl;
    return 0;
}

某算法比赛? B - Erorr(二分 + 贪心)

Description:

​ 给定int数组a 要求构造出一个严格上升int数组b 要求对于i = [1, n] abs(a[i] - b[i]) <= eps

​ 求整数eps的最小值

Solution:

​ 因为满足单调性 且时间复杂度大概就是卡在了nlgn 我首先就是想到二分的写法

​ 要求构造严格上升数组b 那么b的前面的项越小越好 这是我们要贪心的点

​ namo 我们简单的判断一下 当a数组加上x都不如b的上一项的时候 证明x太大了 false 其余都贪

Code:

int n;
const int N = 2000010;
int a[N], b[N];

bool check(int x)
{
    for(int i = 0; i < n; i++)  b[i] = a[i];
    b[0] -= x;
    b[0] = max(1, b[0]);
    for(int i = 1; i < n; i++)
    {
        if(b[i] + x <= b[i - 1])    return false; //最大的可能都不能构成上升 直接寄
        
        if(b[i] - x > b[i - 1])
            b[i] -= x; //贪心 前面的项越小越好
        else 
            if(b[i] + x > b[i - 1])
                b[i] = b[i - 1] + 1;//必定b[i] >= b[i - 1] + 1 贪
    }
    return true;
}

int main()
{
    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];
    
    int l = 0, r = 0x3f3f3f3f;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(check(mid))  r = mid;
        else l = mid + 1;  
    }
    cout << r << '\n';
    return 0;
}

蓝桥杯2019 修改数组(并查集维护数值)

Description:

​ 给定长度为n的数组a a中可能有重复的整数存在

​ 现在Bob要构造一个新的数组b

​ 要求bi是a1~ai-1中的没出现过且大于等于bi的最小整数

5 
2 1 1 3 4 
2 1 3 4 5

Solution:

​ 如果是暴力的写法 那就是去枚举i 用数组记录是否存在 然后用while为bi++ 很明显会超时

​ 我们可以用并查集来维护这个数是否被输出过 若被输出过就输出这个数+1的数 以此类推

Code:

#include <bits/stdc++.h>

using namespace std;
int fa[1000010]; //维护当遇到i时该输出的值

int fd(int x)
{
    if(fa[x] != x)  fa[x] = fd(fa[x]);
    return fa[x];
}

int main()
{
    int n, x;
    cin >> n;
    for(int i = 1; i <= n; i++)
        fa[i] = i;
    
    for(int i = 1; i <= n; i++)
    {
        cin >> x;
        int t1 = fd(x);
        x = t1;
        cout << x << ' ';

        fa[x] = fd(t1 + 1); //下一次遇到x的时候要输出x+1
    }
    return 0;
}

ABC 238 E - Range Sums(并查集 区间合并)

题目链接:https://atcoder.jp/contests/abc238/tasks/abc238_e

Description:

​ 有一个长度为n的未知数组 告诉你q次[l, r]的区间和 请问是否能够通过q个信息 得到位置数组和

Solution:

​ [1, 3] [3, 4]就可以得到[1, 4]

​ 那[1, 3] [2, 4]则不可以得到[1, 4]

​ 原理暂时还不是很清楚 先当做例题记下来

Code:

int fa[200010];
int n, m, l, r;

int fd(int x)
{
    if(fa[x] != x)  fa[x] = fd(fa[x]);
    return fa[x];
}

int main()
{
    cin >> n >> m;

    for(int i = 0; i < 200010; i++)  fa[i] = i;

    while(m --)
    {
        cin >> l >> r;
        fa[fd(l - 1)] = fd(r);  //l-1到r是差分和
        //将l1-1并入到r1  那么如果有[l2, r2]r2 == l1 - 1 那么这代表我们知道了[l2, r1]和
    }

    if(fd(0) == fd(n))  cout << "Yes\n"; //如果我们知道了[1, n]的区间和 那就成功了
    else cout << "No\n";
    return 0;
}

ABC 238 B - Piasa(模拟)

题目链接:https://atcoder.jp/contests/abc238/tasks/abc238_b

Description:

​ 给定一个披萨 每次在12点方向切一刀 读入n个数 每次顺时针转动x度 再在12点方向切一刀

​ 请问切完n+1刀后的相邻两刀之间最大角度

Solution:

​ 模拟转动即可 然后用bool记录在角度x处切下一刀

Code:

map<int, bool> mp;

int main()
{
    int n;
    cin >> n;
    mp[0] = true; //开始的时候切一刀
    mp[360] = true; //0 和 360是重合的 只不过一个在起点一个在终点
    int cur = 0;
    for(int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        cur = (cur + x) % 360; 
        mp[cur] = true; //n刀
    }
    
    vector<int> res;
    for(auto x : mp)
        res.push_back(x.first);
    
    int ans = 0;
    for(int i = 1; i < res.size(); i++)
        ans = max(ans, res[i] - res[i - 1]); //枚举相邻两刀取max
        
    cout << ans << endl;
    return 0;
}

明天早上上一节高数

补高数作业

下午上一节物理 上一节二分

晚上做二分题单 kuangbin搜索一题

做天际线问题 https://leetcode-cn.com/problems/the-skyline-problem/

晚上背单词 刷水题

举报

相关推荐

2022_01_04日结

2022-01-04每日刷题打卡

cs学习记录-01

Docker学习记录-01

毕设记录01-2022-0301

ADB学习01-2022-01-07

前端学习笔记记录01

区块链学习记录01

0 条评论