Submission #1084338

#TimeUsernameProblemLanguageResultExecution timeMemory
108433879brueSeptember (APIO24_september)C++17
100 / 100
329 ms29680 KiB
#include "september.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct segTree{
    int tree[400002];

    void init(int i, int l, int r){
        tree[i] = 0;
        if(l==r) return;
        int m = (l+r)>>1;
        init(i*2, l, m);
        init(i*2+1, m+1, r);
    }

    void update(int i, int l, int r, int x, int v){
        if(l==r){
            tree[i] = v;
            return;
        }
        int m = (l+r)>>1;
        if(x<=m) update(i*2, l, m, x, v);
        else update(i*2+1, m+1, r, x, v);
        tree[i] = max(tree[i*2], tree[i*2+1]);
    }

    int query(int i, int l, int r, int v){ /// [1, i] 최댓값이 v보다 큰 인 최소 i 반환
        if(tree[i] <= v) return -1;
        if(l==r) return l;
        int m = (l+r)>>1;
        if(tree[i*2] > v) return query(i*2, l, m, v);
        else return query(i*2+1, m+1, r, v);
    }
} tree;

struct UnionFind{
    int par[100002];
    void init(int n){
        for(int i=1; i<=n; i++) par[i] = i;
    }

    int find(int x){
        if(x == par[x]) return x;
        return x = find(par[x]);
    }

    void merge(int x, int y){
        x = find(x), y = find(y);
        if(x>y) swap(x, y);
        par[y] = x;
    }
} dsu[5];

struct Query{
    int a, b;
    Query(int a, int b): a(a), b(b){}
};

int n, m;
int par[100002];
vector<int> link[100002];
int arr[5][100002], ord[5][100002];
int DP[100002];

void dfs(int x){
    for(int y: link[x]){
        if(x) DP[y] = min(DP[y], DP[x]);
        dfs(y);
    }
}

int solve(int N, int M, vector<int> F, vector<vector<int>> S) {
	n = N, m = M;
	for(int i=1; i<n; i++) par[i] = F[i], link[par[i]].push_back(i);
	for(int i=0; i<m; i++) for(int j=1; j<N; j++){
        arr[i][j] = S[i][j-1];
        ord[i][arr[i][j]] = j;
	}

	vector<Query> queries;

    /// Case 1
    for(int d=0; d<m-1; d++){
        tree.init(1, 1, n-1);
        for(int i=1; i<n; i++){
            int x = tree.query(1, 1, n-1, ord[d+1][arr[d][i]]);
            if(x != -1) queries.push_back(Query(arr[d][x], arr[d][i]));
            tree.update(1, 1, n-1, i, ord[d+1][arr[d][i]]);
        }
    }

    /// Case 2
    for(int d=0; d<m; d++){
        for(int i=0; i<n; i++) DP[i] = ord[d][i];
        dfs(0);
        for(int i=0; i<n; i++){
            if(DP[i] < ord[d][i]){
                queries.push_back(Query(arr[d][DP[i]], i));
            }
        }
    }

    /// 본격 작업 시작
    for(int d=0; d<m; d++) dsu[d].init(n-1);

    while(!queries.empty()){
        int A = queries.back().a, B = queries.back().b; queries.pop_back();
        for(int d=0; d<m; d++){
            int ad = dsu[d].find(ord[d][A]), bd = dsu[d].find(ord[d][B]);
            if(ad > bd) swap(ad, bd);
            while(ad != bd){
                queries.push_back(Query(arr[d][bd-1], arr[d][bd]));
                dsu[d].merge(bd-1, bd);
                bd = dsu[d].find(bd);
            }
        }
    }

    int ans = 0;
    for(int i=1; i<n; i++) if(dsu[0].find(i) == i) ans++;

    /// 초기화
    for(int i=0; i<=n; i++){
        link[i].clear();
        DP[i] = 0;
    }

    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...