Submission #1296677

#TimeUsernameProblemLanguageResultExecution timeMemory
1296677tschav_Obstacles for a Llama (IOI25_obstacles)C++20
83 / 100
154 ms72556 KiB
#include "obstacles.h"
#include <bits/stdc++.h>
using namespace std;

class DSU {
    vector<int> parent, size;  
    public:
    int sets;
    DSU(int N = 0) {
        init(N);
    }
    void init(int N){
      this->parent.resize(N);
      this->size.resize(N, 1);
      for(int i = 0; i < N; i++)
          this->parent[i] = i;
      this->sets = N;
    }
    int find(int x) {
        if(this->parent[x] != x) {
            this->parent[x] = find(this->parent[x]);
        }
        return this->parent[x];
    }
    void unite(int x, int y) {
        int a = find(x);
        int b = find(y);
        if (a != b) {
            if (this->size[a] < this->size[b]) swap(a, b);
 
            this->parent[b] = a;
            this->size[a] += this->size[b];
        }
    }
    int get_size(int x) {
        return this->size[find(x)];
    }
    void clear() {
        int N = this->parent.size();
        for (int i = 0; i < N; i++) {
            this->parent[i] = i;
            this->size[i] = 1;
        }
        this->sets = N;
    }
};

template <typename T, T (*op)(T, T)>
struct SparseTable {
    int N, LOG;
    vector<vector<T>> st;

    void build(const vector<T> &v) {
        N = v.size();
        LOG = 32 - __builtin_clz(N);
        st.assign(LOG, vector<T>(N));

        st[0] = v;

        for (int k = 1; k < LOG; k++) {
            int len = 1 << k;
            int half = len >> 1;
            for (int i = 0; i + len <= N; i++) {
                st[k][i] = op(st[k-1][i], st[k-1][i+half]);
            }
        }
    }

    T query(int l, int r) const {
        --r;
        int len = r - l + 1;
        int k = 31 - __builtin_clz(len);
        return op(st[k][l], st[k][r - (1<<k) + 1]);
    }
};

int dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};

vector<int> T,H;

vector<int> down,lt,rt,downmx;

int n,m;

DSU dsu;

int maxf (int x,int y){
    return max(x,y);
};

struct Node {
    int idx;
    int val;
};

Node nmaxf (Node x, Node y){
    Node z;
    if(x.val < y.val) swap(x,y);
    z.val = x.val;
    z.idx = x.idx;
    return z;
}

void initialize(vector<int> t, vector<int> h) {
    n = t.size();
    m = h.size();
    T=t;
    H=h;

    dsu.init(m);

    downmx.resize(m,0);
    down.resize(m,0);
    lt.resize(m,0);
    rt.resize(m,0);

    static const int INF = 1e9+1;

    vector<int> st1(n);
    st1[0] = T[0];
    for (int i = 1; i < n; ++i)
        st1[i] = min(st1[i-1], T[i]);


    SparseTable<int,maxf> st2;

    st2.build(h);


    vector<Node> ret(n);

    for(int i = 0; i < n; ++i){
        Node qe;
        qe.idx = i;
        qe.val = T[i];
        ret[i] = qe;        
    }

    Node def;
    def.idx = 0;
    def.val = 0;

    // SegTree<Node> st3 = SegTree<Node>(n,def,[&],ret);

    SparseTable<Node,nmaxf> st3;
    st3.build(ret);

    for(int i = 0; i < m; ++i) {
        if(t[0] <= h[i]){
            down[i] = -1;
        }else{
            int l = 1, r = n;
            int ans = 0;

            while (l <= r) {
                int md = (l + r) >> 1;

                if (st1[md-1] > H[i]) {
                    ans = md;
                    l = md+1;
                } else {
                    r = md-1;     
                }
            }
            down[i] = ans-1;
            downmx[i] = (st3.query(0,ans)).idx;
        }
    }

    for(int i = 0; i < m; ++i){
        if(down[i]==-1)continue;
        int l = i, r = m;
        int ans = i;

        while (l <= r) {
            int md = (l + r) >> 1;

            if (st2.query(i, md) < T[downmx[i]]) {
                ans = md;
                l = md+1;
            } else {
                r = md-1;     
            }
        }
        rt[i] = ans-1;
    }

    for(int i = 0; i < m; ++i){
        if(down[i]==-1)continue;
        int l = 0, r = i;
        int ans = i+1;

        while (l <= r) {
            int md = (l + r) >> 1;

            if (st2.query(md, i+1) < T[downmx[i]]) {
                ans = md;
                r = md-1;
            } else {
                l = md+1;     
            }
        }
        lt[i] = ans;
    }

    for(int i = 0; i + 1< m; ++i){
        if(down[i] >= 0 and down[i+1] >=0){
            dsu.unite(i,i+1);
        }
    }

    // SegTree<int> dst(m,0,[&](auto x, auto y){
    //     return max(x,y);
    // },down);

    SparseTable<int,maxf> dst;
    dst.build(down);

    for(int i = 0; i < m; ++i){
        if(down[i] == -1) continue;
        int curr = downmx[i];
        int idx = i;
            
        int l = i+1, r = rt[i];
        int ans = i;

        while (l <= r) {
            int md = (l + r) >> 1;

            if (dst.query(i+1, md+1) >= curr) {
                ans = md;
                r = md-1;
            } else {
                l = md+1;     
            }
        }

        if(ans != i){
            dsu.unite(ans,i);
        } 
    }

    for(int i = 0; i < m; ++i){
        if(down[i] == -1) continue;
        int curr = downmx[i];
        int idx = i;
            
        int l = lt[i], r = i-1;
            int ans = i;

            while (l <= r) {
                int md = (l + r) >> 1;

                if (dst.query(md, i) >= curr) {
                    ans = md;
                    l = md+1;
                } else {
                    r = md-1;     
                }
            }

        if(ans != i){
            dsu.unite(ans,i);
        } 
    }
}

bool can_reach(int L, int R, int S, int D) {
  
	int r1 = dsu.find(S);
	int r2 = dsu.find(D);

	return (r1==r2);
}
#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...