USACO SILVER::2020 US Open Contest Cereal

Cereal

Point

Design(x)

Big O(time)

Big O(memory)

Code(x)

#include<bits/stdc++.h>
#define endl '\n'
#define rep(i,a,b) for(int i=a;i<b;i++)
#define r_rep(i,a,b) for(int i=a;i>b;i--)
#define all(v) (v).begin(), (v).end()
#define f first
#define s second
#define pb push_back
#define vi vector<int>
#define vpi vector<pair<int,int> >
#define vvpi vector<vector<pair<int,int> > >
#define EMPTY 0
typedef long long ll;
const int MAXN = 100000 + 10;
using namespace std;

int n, m;
int ans[MAXN];
int cereal[MAXN]; // 해당 시리얼을 차지한 소의 인덱스
int f[MAXN], s[MAXN];

void process(){
    cin >> n >> m;
    rep(i, 0, n) cin >> f[i] >> s[i];

    int cnt = 0;
    r_rep(i, n-1, -1){
        int j = i; // who
        int pos = f[i]; // want to take position of cereal
        while(1){
            if(cereal[pos] == EMPTY){ // 비어있으면 바로 차지하고
                cnt++;
                cereal[pos] = j;
                break;
            }else if(cereal[pos] < j){ // 누가 있는데, 나보다 앞에 있는 소가 차지하고 있으면 포기!
                break;                 // 신기한건 이게 소 중심이 아니라, 시리얼 중심이라는 점. 그래서 second 비벼보지 않음
            }else{ // 누가 있는데, 나보다 뒤에 있는 소가 차지하고 있음!
                int tmp = cereal[pos];
                cereal[pos] = j;
                // 현재 시리얼을 원래 차지하고 있던 뒤에 있는 소의 second가 현재 시리얼 위치였다면 break
                // 즉, 새로 온 소가 해당 위치를 차지하고 종료.
                if(pos == s[tmp]) break;
                // 그렇지 않다면, 현재 시리얼을 차지하고 있던 뒤에 있던 소의 second 위치를 또 탐색해주기.
                j = tmp;
                pos = s[tmp];
            }
        }
        ans[i] = cnt;
    }
    rep(i, 0, n) cout << ans[i] << endl;
}

int main(){
    process();
    return 0;
}