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) ? '\n' : ' ');
        }
    }
    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

 

posted @ 2020-09-17 22:34  雪溯  阅读(199)  评论(0编辑  收藏  举报