zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 95 (Rated for Div. 2)

    Problem A

    题意:开局:1A 两种操作: 1A->xA,yA->1B,问最少多少次操作能获得kA和kB

    思路:1A->xA这个操作增加了x-1 A

    要获得kB,那肯定需要y* kA + k个操作

    所以总共需要(y+1) * k个A,这些需要 ceiling(((y + 1) * k - 1) / (x - 1))个操作

    总共 ceiling(((y + 1) * k - 1) / (x - 1)) + k个操作

    #include <iostream>
    using namespace std;
    int main(){
    int t;
    long long x, y, z;
    cin >> t;
    while(t--){
    cin>>x>>y>>z;
    long long swap = z;
    auto x1 = x-1;
    swap += (z + (z * y) + x1-2)/x1;
    cout<<swap<<endl;}
    return 0;}
    View Code

    Problem B

    题意:使前缀和为负的最大序号尽可能小

    思路:很简单,能排序的位置按照值大优先排序

    #include <iostream>
    #include <algorithm>
    using namespace std;
    int a[100];
    bool lk[100];
    int b[100];
    int main()
    {
        int t, n;
        cin >> t;
        while (t--)
        {
            cin >> n;
            int m = 0;
            for (int i = 0; i < n; i++)
            {
                cin >> a[i];
            }
            for (int i = 0; i < n; i++)
            {
                cin >> lk[i];
                if (!lk[i])
                    b[m++] = a[i];
            }
            sort(b, b + m);
     
            for (int i = 0; i < n; i++)
            {
                if (!lk[i])
                    a[i] = b[--m];
                cout << a[i] << ((i == n - 1) ? '
    ' : ' ');
            }
        }
        return 0;
    }
    View Code

    Problem C

    题意:A,B一起取n个子,都只能取1或2个,A取到1会罚1分,B取1不会罚分,0二人都不罚分,现在A,B合作,A先开始,要使罚分最低。

    思路:只有三种选择:一起走2步,第一步A;一起走3步,第一步A;一起走4步,前2步A;

    错误原因:数组开的太小,也是WA不是LE

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    int lk[200000];
    int dp[200005];
    int main()
    {
        int t, n;
        cin >> t;
        while (t--)
        {
            cin >> n;
            int m = 0;
            memset(lk, 0, sizeof(lk));
            for (int i = 0; i < n; i++)
            {
                cin >> lk[i];
            }
            memset(dp, 0x7f, sizeof(dp));
            dp[0] = 0;
            for (int i = 0; i < n; i++) {
                for (int sum = 2; sum <= 4; sum++) {
                    int skippt = lk[i];
                    if (sum > 3 && i < n - 1)skippt += lk[i + 1];
                    dp[i + sum] = min(dp[i + sum], dp[i] + skippt);
                }
            }
            for (int i = 1; i < 4; i++)dp[n] = min(dp[n], dp[n + i]);
            cout << dp[n] << endl;
        }
        return 0;
    }
    View Code

    Problem D

    题意:有若干堆垃圾,可以选择往左扫或者右一步,要求把所有垃圾合并成最多两堆

    思路:

    一开始以为和连通图有关,后来发现就只是总长减去最大的线段间隔,也就是相当于将第一堆到线段左边那堆扫到一起,将线段右边那堆一直到最后一堆扫到一起,变成两个子过程,每个子过程相当于相对于中点由外向内合并所有,将所有堆都扫到中点。所以,只需要维护最大的线段这一个属性。

    #include <vector>
    #include <string>
    #include <queue>
    #include <iostream>
    #include <set>
    #include <queue>
    #include <algorithm>
    using namespace std;
    int p[100000];
    
    int main() {
        freopen("input.txt", "r", stdin);
        int n, q;
        set<int> st;
        priority_queue<pair<int, int> > prs;
        cin >> n >> q;
        for (int i = 0; i < n; i++) {
            cin >> p[i];
        }
        sort(p, p + n);
        for (int i = 0; i < n; i++) {
            st.insert(p[i]);
            if (i > 0)prs.push(make_pair(p[i] - p[i - 1], p[i]));
        }
        if (n <= 2) {
            cout << 0 << endl;
        }
        else {
            int start_x = *st.begin();
            int end_x = *prev(st.end(), 1);
            int big_gap = 0;
            while (!prs.empty()) {
                int gap_end_x = prs.top().second;
                int gap = prs.top().first;
                auto tmpit = st.find(gap_end_x);
                if (tmpit == st.end() || tmpit == st.begin() || *prev(tmpit, 1) != gap_end_x - gap) {
                    prs.pop(); continue;
                }
                big_gap = gap;
                break;
            }
            cout << end_x - start_x - big_gap << endl;
        }
        for (int ci = 0; ci < q; ci++) {
            int op, x;
            cin >> op >> x;
            if (op == 1) {
                st.insert(x);
            }
            auto it = st.find(x);
            auto it_prev = (it == st.begin()) ? it : prev(it, 1);
            auto it_next = next(it, 1);
            if (op == 0) {
                if (it != st.begin() && it_next != st.end()) {
                    prs.push(make_pair((*it_next - *it_prev), *it_next));
                }
                st.erase(x);
            }
            else {
                if (it != st.begin()) {
                    prs.push(make_pair((x - *it_prev), x));
                }
                if (it_next != st.end()) {
                    prs.push(make_pair((*it_next - x), *it_next));
                }
            }
            if (st.size() <= 2) {
                cout << 0 << endl;
            }
            else {
                int start_x = *st.begin();
                int end_x = *prev(st.end(), 1);
                int big_gap = 0;
                while (!prs.empty()) {
                    int gap_end_x = prs.top().second;
                    int gap = prs.top().first;
                    auto tmpit = st.find(gap_end_x);
                    if (tmpit == st.end() || tmpit == st.begin() || *prev(tmpit, 1) != gap_end_x - gap) {
                        prs.pop(); continue;
                    }
                    big_gap = gap;
                    break;
                }
                cout << end_x - start_x - big_gap << endl;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MDK中STM32使用Printf函数详细解析【转载】
    QLCDNumber设置背景色和显示数字颜色【转载】
    C++的引用类型【转载】
    C++默认构造函数
    QT 中“ std::cerr ”的使用方法【转载】
    ubuntu 挂载exfat
    QAbstractSocket::connectToHost() called when already looking up or connecting/connected to
    Qt下 QString转char*
    10种软件滤波方法的示例程序
    详解Top命令 输出命令行选项及代码
  • 原文地址:https://www.cnblogs.com/xuesu/p/13688125.html
Copyright © 2011-2022 走看看