상세 컨텐츠

본문 제목

CF 986 problem C 풀이 정리

codeforces

by 김관중 2024. 11. 22. 11:03

본문

버츄얼 돌다 만난 문제. 투포인터랑 부분합을 더 많이 풀어봐야겠다는 생각이 들었다.

 

일단 버츄얼 중에는 B를 만나고 멘탈에 많은 타격이 들어와 슼보를 왔다갔다 하며

 

C를 풀까말까 했다. 결국 B와 C 모두 풀지 못했다.

 

문제 핵심 아이디어

$pfx$ 배열의 단조성을 이용하여 이분탐색 or 투포인터를 사용해야한다.

 

일단 m개의 creature에게 분배될 수 있는지부터 확인해야 하기 때문에

 

이를 관리해주어야 한다.

 

$pfx[i]$를 앞에서부터 $i$ 까지 봤을 때 분배해줄 수 있는 creature 수라고 하고

 

$sfx[i]$를 뒤에서부터 $i$ 까지 봤을 때 분배해줄 수 있는 creature 수라고 하자. 

 

이는 투포인터로 연속된 구간의 합을 합/차 해가며 그리디하게 $pfx$ 배열에 기록해주면 된다.

 

포인터 $start$에 따른 $end$를 구간 합이 작을 동안 증가시키고 가능한 경우라면 $start$에서 올 수 있게 기록하면 된다.

 

이때 $pfx[end]$ 값을 그리디하게 선택해야하기 때문에 $start$ 포인터를 for문으로 관리해준다.

 

그리고 마지막에서도 투포인터가 사용되는데

 

각 $pfx[i]+sfx[j]>=m$을 만족하는 $j$의 최댓값을 구해주고 $[i+1,j-1]$까지를 Alice에게 주면 된다.

 

따라서 for문으로 $i$를 증가시키면서 최대 $j$ 값을 찾고 그때 Alice가 얻을 수 있는 양을 구해주면 된다. 

 

코드는 다음과 같다.

 

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    int t;
    cin >> t;
    while(t--){
        int n,m;
        ll v;
        cin >> n >> m >> v;
        vector<ll> a(n),sum(n+1,0);
        for(int i=0;i<n;i++){
            cin >> a[i];
            sum[i+1]=sum[i]+a[i];
        }
        auto solve=[&]() -> vector<int> {
            vector<int> pfx(n+1,0);
            int e=0;
            ll rsum=0;
            for(int s=0;s<n;s++){
                while(e<n && rsum<v){
                    rsum+=a[e];
                    e++;
                    pfx[e]=max(pfx[e],pfx[e-1]);
                }
                if(rsum>=v) pfx[e]=pfx[s]+1;
                rsum-=a[s];
            }
            for(int i=1;i<=n;i++) pfx[i]=max(pfx[i],pfx[i-1]);
            return pfx;
        };
        auto getsum=[&](int a, int b){ return sum[b]-sum[a]; };
        auto pfx=solve();
        if(pfx[n]<m){
            cout << "-1\n";
            continue;
        }
        reverse(a.begin(),a.end());
        auto sfx=solve();
        reverse(sfx.begin(),sfx.end());
        int e=0;
        ll ans=0;
        for(int s=0;s<n;s++){
            while(e<n && pfx[s]+sfx[e+1]>=m) e++;
            if(pfx[s]+sfx[e]>=m) ans=max(ans,getsum(s,e));
        }
        cout << ans << '\n';
    }
    return 0;
}

'codeforces' 카테고리의 다른 글

CF 986 problem B 풀이 정리  (0) 2024.11.11

관련글 더보기

댓글 영역