Codeforces Round 1039 (Div. 2) 1 ~ D

今天这场有点狗运,C和D带点guess成分
但这些都得益于超✌的指导,让我茅塞顿开
(后面因为手贱重复提交罚时暴涨,我是傻逼,就当是暂避锋芒吧)

7346c5a4fc8ac79927d4da8f43f88cad


感觉这场像AI一样,搁编译器里推了可长时间(
不过也是因为之前总是犯错,还没想明白就下手写代码,白白浪费罚时
也算是一种强制自己的方法


A

/*====================My_Solution====================//

    每次销毁垃圾都会导致剩下的*2
    我们要对每个垃圾的“次数”进行排序
    然后按次数从小到大去选择

//====================My_Solution====================*/ 

void solve () {
    i64 n, c;
    std::cin >> n >> c;

    std::vector<i64> a(n + 1), b;
    std::set<int> st;

    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        if (a[i] <= c) {
            b.push_back( std::__lg(c / a[i])  );
        }
    }
    std::sort(b.begin(), b.end());

    int cnt = 0;
    for (auto it : b) {
        if (cnt <= it) {
            cnt++;
        }
    }
    std::cout << n - cnt << '\n';
}


B

/*====================My_Solution====================//

    从双端队列中取数,使得构成的新数组中
    每一次都是符合要求的,即没有连续五个递增或递减的子序列

    如果原序列有序,那么我们可以轻易获得
    如果是乱序,先取大的,再取小的
    循环往复,即可获取答案

//====================My_Solution====================*/ 

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

    std::deque<int> p;
    std::vector<int> q;
    std::string ans = "";

    for (int i = 1; i <= n; i++) {
        int x;
        std::cin >> x;
        p.push_back(x);
    }

    int cnt = 1;
    while (p.size()) {
        if (cnt % 2 == 1) {
            int x = p.front();
            int y = p.back();

            q.push_back(x > y ? x : y);
            ans += x > y ? "L" : "R";
            x > y ? p.pop_front() : p.pop_back();
        } else {
            int x = p.front();
            int y = p.back();

            q.push_back(x < y ? x : y);
            ans += x < y ? "L" : "R";
            x < y ? p.pop_front() : p.pop_back();
        }
        cnt++;
    }
    std::cout << ans << '\n';
}



C

/*====================My_Solution====================//

    把全0数组变为目标数组
    操作方式是任意选一个数x(不小于数组的最小值)
    然后找到第一个a[i] < x,让a[i] += x
    以上视为一次操作

    先递增后递减的数组就是可以的吗?
    0 0 0
    40 0 0
    40 20 0
    40 60 0
    40 60 20
    40 60 
    也就是说,单纯递增也不一定满足要求
    如果某个数字大于等于数组最小值的两倍了,那就不可以了

    非递增的序列,显然是可以构造出来的
    我们的问题,仅在于是否能构造前端递增的序列
    4 5 6可以吗
    0 0 0 
    4 0 0
    4 1 0
    4 5 0
    4 5 2
    4 5 6
    4 5 6 3
    4 5 6 7
    4 5 6 7 4
    我们可以看到,构造到8就不可以了
    也就是说,一段连续递增序列中不能有任意一个数字>= 2 * min(递增)

    不对,不是一定只能构造出先递增后递减的序列的
    5 2 2 3
    0 0 0 0
    5 0 0 0
    5 2 0 0 
    5 2 2 0
    5 2 2 1
    5 2 2 3
    我们应当用f[i]表示第i位能构造出的最大数字
    则f[i] = 2 * min(1 ~ i-1) - 1

//====================My_Solution====================*/ 

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

    std::vector<i64> a(n + 1);
    std::vector<i64> premin(n + 1, INF);
    std::vector<i64> f(n + 1);

    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        premin[i] = std::min(premin[i - 1], a[i]);
    }

    f[1] = a[1];
    for (int i = 2; i <= n; i++) {
        f[i] = 2 * premin[i - 1] - 1;

        if (a[i] > f[i]) {
            std::cout << "NO\n";
            return;
        }
    }
    std::cout << "YES\n";
}


D

/*====================My_Solution====================//

    给定一个排列,一定满足max(p[i], p[i + 1]) > p[i + 2]
    然后需要求所有[l, r]区间的最长递减子序列的长度之和??

    这个数据范围,O(n)或者O(logn)
    感觉O(logn)可以排除了,乱序的排列用不了二分,也没有二分答案

    我们只能从排列的性质入手,这个性质还是很有意思的
    也就是说,只要长度>= 3,最长递减子序列长度至少为2
    能不能考虑O(n)的dp呢

    最长递减子序列用dp是O(n ^ 2)的复杂度,能不能递推出来?
    f[i]表示第i位多出来的答案数,对于f[i]和f[i - 1],
    增加了[1, i] --> [i, i]总共i个区间

    观察1st样例
    1 2+1 3+2+1 == 10
    1 3 6
    观察2nd样例
    1 2+1 3+2+1 3+2+1+1 == 17
       +2  +3   
    1 3 6 7
    观察3rd样例
    1 2+1 2+1+1 3+2+2+1 3+2+2+1+1 4+3+3+2+2+1
       +2         +2+2               +2+2+2
    1 3 4 8 9 15

    最终答案就是:
    if a[i] < a[i - 1] f[i] = f[i - 1] + i
    if a[i] > a[i - 1] f[i] = f[i - 1] + 1 

//====================My_Solution====================*/ 

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

    std::vector<int> a(n + 1);  
    std::vector<i64> f(n + 1);

    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
    }

    i64 ans = 1;
    f[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i] > a[i - 1]) {
            f[i] = f[i - 1] + 1;
        } else {
            f[i] = f[i - 1] + i;
        }
        ans += f[i];
    }
    std::cout << ans << '\n';
}

posted @ 2025-07-28 00:54  _彩云归  阅读(47)  评论(1)    收藏  举报