Codeforces Round 935 (Div. 3)(A-G)

题目链接:Codeforces Round 935 (Div. 3)

 

A. Setting up Camp
思路:贪心,a自己组队,b优先自己组,多余的尽量和c组,如果能一个不留即可,c尽量三人一组,多出来的加一组
void solve(){
    ll a, b, c;
    cin >> a >> b >> c;
    ll ans = a;
    ans += b / 3;
    b -= b / 3 * 3;
    if(b == 0) ans += c / 3 + (c % 3 != 0);
    else{
        ll cha = 3 - b;
        if(cha > c) ans = -1;
        else{
            c -= cha;
            ans ++;
            ans += c / 3 + (c % 3 != 0);
        }
    }
    cout << ans << '\n';
}

B. Fireworks

void solve(){
    ll a, b, m;
    cin >> a >> b >> m;
    ll ans = m / a + 1;
    ans += m / b + 1;
    cout << ans << '\n';
}

C. Left and Right Houses

题意:有n间房子,要在最前方或者最后或者两间房子之间建立一条街道,标记为0的房子希望在街道左边,标记为1的希望在街道右边,求至少能满足街道两边各一半(向上取整)且最靠近中央的的街道(如果多个满足,取最小),街道的位置是它前一间房子的下标,特殊的最前面的街道为0

思路:求一下前缀1的数量,枚举每一个建造街道的点,用差分求出两边是否满足要求,最后取最靠近中点且最小的街道

void solve(){
    int n;
    string s;
    cin >> n >> s;
    vector<ll> a(n + 1);
    for(int i = 1; i <= n; i ++){
        if(s[i - 1] == '1'){
            a[i] = 1;
        }
    }
    for(int i = 1; i <= n; i ++) a[i] += a[i - 1];
    
    double n1 = n * 1.0;
    double ans = 1.0 * n1;
    int idx = 0;
    if(a[n] >= (n / 2 + (n % 2 != 0))){
        ans = fabs(n1 / 2 - 0);
        idx = 0;
    }
    for(int i = 1; i <= n; i ++){
        ll lsum = i - a[i], rsum = a[n] - a[i];
        ll lp = i / 2 + (i % 2 != 0), rp = ((n - i) / 2 + ((n - i) % 2 != 0));
        if(lsum >= lp && rsum >= rp){
//            cout << i << '\n';
            if(fabs(n1 / 2 - i * 1.0) < ans){
                ans = fabs(n1 / 2 - i * 1.0);
                idx = i;
            }
        }
    }
    cout << idx << '\n';
}

D. Seraphim the Owl

思路:从后往前枚举,只在当前位取a[i],否则取min(a[i], b[i])

void solve(){
    ll n, m;
    cin >> n >> m;
    vector<ll> a(n + 1), b(n + 1);
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    ll ans = 1e18, sum = 0;
    for(int i = n; i >= 1; i --){
        if(i <= m){
            ll res = sum + a[i];
            ans = min(ans, res);
        }
        sum = sum + min(a[i], b[i]);
    }
    cout << ans << '\n';
}

E. Binary Search

思路:按题意模拟二分,最后交换最终位置和目标答案的位置

void solve(){
    ll n, x;
    cin >> n >> x;
    vector<ll> a(n + 1);
    int idx = 0;
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
        if(a[i] == x) idx = i;
    }
    ll l = 1, r = n + 1;
    while(r - l != 1){
        ll mid = r + l >> 1;
        if(a[mid] <= x) l = mid;
        else r = mid;
    }
    if(a[l] == x) cout << 0 << '\n';
    else{
        cout << 1 << '\n' << l << ' ' << idx << '\n';
    }
}

F. Kirill and Mushrooms

题意:每一朵蘑菇的价值为v[i],但是如果采n朵蘑菇,p[1]-p[n-1]的蘑菇都变成0(注意,这里不是p为1-(n-1)的蘑菇变为0,而是前n-1个p对应的位置变为0),同时,采得蘑菇的价值为采得蘑菇的数量和最小价值的蘑菇的价值的乘积

思路:先排序,从大到小来模拟,如何删除不合格的蘑菇,用set维护即可

void solve(){
    ll n;
    cin >> n;
    vector<ll> a(n + 1), b(n + 1);
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    set<PII> st;
    vector<PII> a1(n + 1);
    for(int i = 1; i <= n; i ++) a1[i] = {a[i], i};
    sort(a1.begin() + 1, a1.end(), cmp);
    ll ans = 0, lens = 0;
    for(int i = 1; i <= n; i ++){
        if(a[a1[i].second] == 0) continue;
        st.insert(a1[i]);
        int len = st.size();
        if(len - 1 >= 1){
            st.erase({a[b[len - 1]], b[len - 1]});
            a[b[len - 1]] = 0;
        }
        int res = st.begin()->first * st.size();
        if(res > ans){
            ans = res;
            lens = st.size();
        }
        else if(res == ans){
            len = st.size();
            lens = min(lens, len);
        }
    }
    cout << ans << ' ' << lens << '\n';
}

G. Cook and Porridge

题意:每个人有两个属性k和s,k是这个人排队的优先级,s是这个人完成一次行动后需要等待的时间,当一个人完成一次行动,就会进入等待,等待s之后重新进入队列,并且他会插到所有优先级比他低的人之前,求在d时间内所有人完成一次行动的最早时间,如果无法所有人都完成一次行动,输出-1

思路:一个大根堆维护当前正在排队的人,一个小根堆维护等待的人,先用后缀max保证初始排队的人是按照原来的顺序来的,接下来每次把大根堆顶拿出来,记录他是否喝过粥,同时把小根堆的等待完毕的人释放出来,最后如果在d时间内所有人都能喝过粥输出最后喝粥的人的时间,否则是-1

typedef tuple<int, int, int> TII;
void
solve(){ int n, d; cin >> n >> d; vector<PII> a(n); for(auto & [x, y] : a) cin >> x >> y; priority_queue<TII> pq; pq.push({a[n - 1].first, -(n - 1), n - 1}); for(int i = n - 2, ma = a[n - 1].first; i >= 0; i --){ ma = max(ma, a[i].first); pq.push({ma, -i, i}); } priority_queue<TII, vector<TII>, greater<TII>> ret;//等待队列 vector<bool> vis(n); int num = 0, cnt = n + 1; for(int i = n + 1; i <= n + d; i ++){ auto [_, __, id] = pq.top(); pq.pop();//队首 if(!vis[id]) vis[id] = true, num ++; if(num == n){ cout << i - n << '\n'; return; } ret.push({i + a[id].second, a[id].second, id});//进入等待队列 while(get<0>(ret.top()) <= i){ auto [time, s, pid] = ret.top(); ret.pop(); pq.push({a[pid].first, -(cnt ++), pid}); } } cout << -1 << '\n'; }

 

 
posted @ 2024-03-22 14:32  Rosmontis_L  阅读(50)  评论(0编辑  收藏  举报