ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • UCPC 2025 예선 후기
    대회 2025. 7. 13. 14:41

    ICPC 팀원인 abra_stone이 전대프연 부회장으로 끌려가서 팀이 터졌다. gs20036도 고등학교 친구들과 팀 한다고 사라져서 런 친구들이랑 직전에 팀 꾸려서 신청했다. juneharold는 코포 퍼플도 찍었던 고수고, dylan0301은 대충 요상한 수학 문제 나오면 먹일 역할로 팀을 구성했다.


    00:02
    A를 읽었다. 전통적인 브론즈 문제였다. 바로 짜서 AC.

    #include<bits/stdc++.h>
    using namespace std;
    
    int x;
    
    int main(){
        int tmp = 0;
        for(int i=0;i<4;i++){
            scanf("%d", &x);
            tmp += x;
        }
        if(tmp+300<=1800) printf("Yes");
        else printf("No");
    }

    00:05
    B를 읽었다. 한 칸이 0이면 답은 총합과 같았고, 한 칸을 0으로 만들 때까지는 2씩 줄어든다. 바로 짜서 AC.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, m;
    ll board[1005][1005];
    
    int main(){
        scanf("%d %d", &n, &m);
        ll mn = 1000000000;
        ll sm = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%lld", &board[i][j]);
                mn = min(mn, board[i][j]);
                sm += board[i][j];
            }
        }
        printf("%lld\n", sm-mn);
    }

    00:17
    E가 풀리길래 읽었다. 각 방음벽은 대충 로그 횟수만큼 사용 가능하니까 나이브를 짜서 AC.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, q, a, b, c;
    ll arr[200005];
    
    int main(){
        scanf("%d", &n);
        for(int i=1;i<=n;i++) scanf("%lld", &arr[i]);
        scanf("%d", &q);
        while(q--){
            scanf("%d", &a);
            if(a==1){
                scanf("%d %d", &b, &c);
                ll tmp = c;
                for(int i=b;i>=1;i--){
                    if(tmp==0) break;
                    ll u = min(tmp, arr[i]);
                    arr[i] += u;
                    tmp -= u;
                }
                tmp = c;
                for(int i=b+1;i<=n;i++){
                    if(tmp==0) break;
                    ll u = min(tmp, arr[i]);
                    arr[i] += u;
                    tmp -= u;
                }
            }
            if(a==2){
                scanf("%d", &b);
                printf("%lld\n", arr[b]);
            }
        }
    }

    00:18-00:23
    juneharold가 I에서 WA를 한 번 받고 AC.


    00:31
    D가 풀리길래 읽었다. 대충 빈 공간 크기 구해 놓고 이분탐색 + 누적 합 하면 되는 문제. 바로 짜서 AC.

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int, int> pi;
    
    int n, h, x, y, q;
    vector<pi> vec;
    int sm[200005];
    
    int main(){
        scanf("%d %d", &n, &h);
        while(n--){
            scanf("%d %d", &x, &y);
            vec.push_back(pi(x, y));
        }
        sort(vec.begin(), vec.end());
        int prv = 0;
        vector<int> val;
        for(auto p: vec){
            if(p.first>prv+1) val.push_back(p.first-prv-1);
            prv = max(prv, p.second);
        }
        if(prv<h) val.push_back(h-prv);
        sort(val.begin(), val.end());
        if(val.empty()){
            scanf("%d", &q);
            while(q--){
                scanf("%d", &x);
                printf("0\n");
            }
            return 0;
        }
        for(int i=val.size()-1;i>=0;i--) sm[i] = sm[i+1]+val[i];
        scanf("%d", &q);
        while(q--){
            scanf("%d", &x);
            if(val.back()<x){
                printf("0\n");
                continue;
            }
            int s = 0;
            int e = val.size()-1;
            while(s^e){
                int m = (s+e)>>1;
                if(val[m]>=x) e = m;
                else s = m+1;
            }
            printf("%d\n", sm[s]-(x-1)*(val.size()-s));
        }
    }

    01:44
    이것저것 읽다가 dylan0301이 H 코드를 힘들게 짜고 있길래 대신 받아와서 구현했다. 예제가 안 나와서 보니까 케이스워크를 조금 더 해줬어야 했다. 친절한 예제에게 감사하며 AC.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 1000000007;
    
    int n, x, y;
    ll fac[1000005], caf[1000005];
    
    ll pw(ll a, ll b){
        ll res = 1;
        while(b){
            if(b%2) res = res*a%mod;
            a = a*a%mod;
            b /= 2;
        }
        return res;
    }
    
    ll inv(ll a){return pw(a, mod-2);}
    ll comb(ll a, ll b){return fac[a]*caf[b]%mod*caf[a-b]%mod;}
    
    ll f(ll a){
        if(a==1) return 1;
        return pw(2, a-2);
    }
    
    ll g(int a, int b){
        if(a==1) return 1;
        if(b==0||b==a) return 0;
        if(b==1||b==a-1) return 1;
        return comb(a-2, b-1);
    }
    
    int main(){
        fac[0] = 1;
        for(int i=1;i<=1000000;i++) fac[i] = fac[i-1]*i%mod;
        caf[1000000] = inv(fac[1000000]);
        for(int i=1000000;i>0;i--) caf[i-1] = caf[i]*i%mod;
        scanf("%d", &n);
        scanf("%d %d", &x, &y);
        if(x>y) swap(x, y);
        if(x==1){
            if(y==2||y==n) printf("%lld", f(n-1));
            else printf("0");
        }
        else if(y==x+1){
            ll res = 0;
            for(int i=1;i<x;i++){
                res = (res+g(n-y+i+1, n-y+1)*f(x-i)%mod)%mod;
            }
            for(int i=y+1;i<=n+1;i++){
                res = (res+g(n+x-i+1, x-1)*f(i-y)%mod)%mod;
            }
            printf("%lld", res);
        }
        else printf("%lld", g(n-y+x, x-1)*f(y-x)%mod*2%mod);
    }

    02:21-02:39
    슼보 보니까 하나만 더 풀면 될 것 같아 다같이 C를 잡았다. 대충 $[s, e]$라는 쿼리가 주어지면 각 구간 $[l, r]$에 대해 $\max(0, r-s, e-l)$을 구하는 문제였다. $r-s$와 $e-l$의 대소는 $r+l$과 $s+e$의 대소와 같으므로 구간의 양 끝 점의 합 기준으로 잘 정렬을 하면 되는데, 음수로 떨어지는 걸 어떻게 해야 할지 고민이었다. juneharold가 오프라인 쿼리를 얘기해서, 한 정렬 기준으로 한쪽에 있는 것만 보면서 나머지 한 정렬 기준으로 쿼리를 날리는 건  typical한 세그 문제였다는 걸 그때서야 깨달았다. juneharold와 내가 각자 코드를 짜기 시작해서 juneharold가 4WA.


    02:40-02:52
    나도 C 첫 제출을 했으나 런타임에러를 받고, 배열 범위를 수정했음에도 WA. 중간에 귀찮아서 대충 잡은 세그 쿼리 범위를 대충 잡으면 안됐었다. 고쳐서 AC.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct interval{
        ll l, r;
        interval(){}
        interval(ll l, ll r): l(l), r(r){}
    };
    struct query{
        ll s, e;
        int idx;
        query(){}
        query(ll s, ll e, int idx): s(s), e(e), idx(idx){}
    };
    typedef pair<ll, ll> pi;
    
    int n, q;
    interval arr[250005];
    query qrr[250005];
    ll res[250005];
    pi ltree[4000005], rtree[4000005];
    
    void lupdate(int node, int s, int e, int l, ll u){
        if(e<l||l<s) return;
        if(s==e){
            ltree[node].first += u*l;
            ltree[node].second += u;
            return;
        }
        int m = (s+e)>>1;
        lupdate(node<<1, s, m, l, u);
        lupdate(node<<1|1, m+1, e, l, u);
        ltree[node] = pi(ltree[node<<1].first+ltree[node<<1|1].first, ltree[node<<1].second+ltree[node<<1|1].second);
    }
    
    pi lquery(int node, int s, int e, int l, int r){
        if(e<l||r<s) return pi(0, 0);
        if(l<=s&&e<=r) return ltree[node];
        int m = (s+e)>>1;
        pi p1 = lquery(node<<1, s, m, l, r);
        pi p2 = lquery(node<<1|1, m+1, e, l, r);
        return pi(p1.first+p2.first, p1.second+p2.second);
    }
    
    void rupdate(int node, int s, int e, int l, ll u){
        if(e<l||l<s) return;
        if(s==e){
            rtree[node].first += u*l;
            rtree[node].second += u;
            return;
        }
        int m = (s+e)>>1;
        rupdate(node<<1, s, m, l, u);
        rupdate(node<<1|1, m+1, e, l, u);
        rtree[node] = pi(rtree[node<<1].first+rtree[node<<1|1].first, rtree[node<<1].second+rtree[node<<1|1].second);
    }
    
    pi rquery(int node, int s, int e, int l, int r){
        if(e<l||r<s) return pi(0, 0);
        if(l<=s&&e<=r) return rtree[node];
        int m = (s+e)>>1;
        pi p1 = rquery(node<<1, s, m, l, r);
        pi p2 = rquery(node<<1|1, m+1, e, l, r);
        return pi(p1.first+p2.first, p1.second+p2.second);
    }
    
    int main(){
        scanf("%d %d", &n, &q);
        for(int i=0;i<n;i++) scanf("%lld %lld", &arr[i].l, &arr[i].r);
        for(int i=0;i<q;i++){
            scanf("%lld %lld", &qrr[i].s, &qrr[i].e);
            qrr[i].idx = i;
        }
        sort(arr, arr+n, [&](interval a, interval b){return a.l+a.r<b.l+b.r;});
        sort(qrr, qrr+q, [&](query a, query b){return a.s+a.e<b.s+b.e;});
        int idx = 0;
        for(int i=0;i<q;i++){
            while(idx<n&&arr[idx].l+arr[idx].r<qrr[i].s+qrr[i].e){
                lupdate(1, 0, 1000001, arr[idx].r, arr[idx].r-arr[idx].l);
                idx++;
            }
            pi p = lquery(1, 0, 1000001, qrr[i].s, 1000000);
            res[qrr[i].idx] += p.first-p.second*qrr[i].s;
        }
        idx = n-1;
        for(int i=q-1;i>=0;i--){
            while(idx>=0&&arr[idx].l+arr[idx].r>=qrr[i].s+qrr[i].e){
                rupdate(1, 0, 1000001, arr[idx].l, arr[idx].r-arr[idx].l);
                idx--;
            }
            pi p = rquery(1, 0, 1000001, 1, qrr[i].e);
            res[qrr[i].idx] += p.second*qrr[i].e-p.first;
        }
        for(int i=0;i<q;i++) printf("%lld\n", 2*res[i]);
    }

    39등으로 본선은 널널하게 진출했다. 예선은 3컴이기도 해서 병렬로 플레를 슥슥 밀어버리는 다른 팀들에 비해 후반에 힘이 좀 빠진 것 같은데, 본선에서는 dylan0301에게 잘 맞는 문제를 주고 juneharold와 하나씩 플레를 잘 미는 것을 목표로 하면 만족스러운 결과가 나오지 않을까 싶다.

    '대회' 카테고리의 다른 글

    SCPC 2025 1차 후기  (0) 2025.07.13
    2024 ICPC Asia Seoul Regional 후기  (1) 2024.12.14
    2024 SCPC 2차 예선 후기 및 풀이  (0) 2024.07.27
    UCPC 2024 예선 후기  (0) 2024.07.15
    2024 현대모비스 알고리즘 경진대회 후기  (0) 2024.07.15
Designed by Tistory.