Codeforces - Multi-Colored-Segments

本文最後更新於:2024年1月12日 下午

Codeforces

出處 Codeforces Round 826 (Div. 3)
難度 2000
標籤 binary search data structures math sortings *2000

Codeforces - Multi-Colored-Segments

Multi-Colored-Segments.cpp

// Author : ysh
// 12/03/2022 Sat 20:17:16.51
// https://codeforces.com/contest/1741/problem/F
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include<debug.h>
#else
#define debug(...) '*'
#define printf(...) '*'
#endif

struct box{
    int a,b,c;
    box(int a = 0,int b = 0,int c = 0):
        a(a), b(b), c(c) {};
    inline bool operator<(box a) {
        return c < a.c;
    }
};

template<typename T>
struct seg_tree{
    int n;
    vector<T>f,hold;

    seg_tree(int n) {
        this->n = n;
        f.resize(n << 2);
        hold.resize(n << 2);
    }

    seg_tree(vector<T>&v) {
        this->n = v.size();
        f.resize(n << 2);
        hold.resize(n << 2);
        mt(1,0,n - 1,v);
    }
    
    void push(int t,int l,int r) {
        f.at(t) = f.at(t) || hold.at(t);
        hold.at(t << 1) = hold.at(t << 1) || hold.at(t);
        hold.at((t << 1) | 1) = hold.at((t << 1) | 1) || hold.at(t);
        hold.at(t) = 0;
    }

    T exact(int t,int l,int r) {
        return f.at(t) || hold.at(t);
    }

    T re(int t,int l,int r) {
        return f.at(t) = (exact((t << 1),l,(l + r) >> 1) || exact((t << 1) | 1,((l + r) >> 1) + 1,r));
    }

    T mt(int t,int l,int r,vector<T>&v) {
        if(l == r) return f.at(t) = v.at(l);
        int mid = (l + r) >> 1;
        return f.at(t) = mt((t << 1),l,mid,v) || mt((t << 1) | 1,mid + 1,r,v);
    }

    void add(int nl,int nr,T v,int t = 1,int l = 0,int r = -1) {
        if(r == -1) r = n - 1;
        if(nr < l || nl > r) return;
        if(l == r) {
            f.at(t) = 1;
            return;
        }
        push(t,l,r);
        int mid = (l + r) >> 1;
        if(nl <= l && nr >= r) {
            hold.at(t) = 1;
            return;
        }
        add(nl,nr,v,t << 1,l,mid),add(nl,nr,v,(t << 1) | 1,mid + 1,r);
        re(t,l,r);
        return;
    }

    T sum(int nl,int nr,int t = 1,int l = 0,int r = -1) {
        if(r == -1) r = n - 1;
        if(nr < l || nl > r) return 0;
        if(l == r) return f.at(t) || hold.at(t);
        push(t,l,r);
        int mid = (l + r) >> 1;
        if(nl <= l && nr >= r) return exact(t,l,r);
        return sum(nl,nr,t << 1,l,mid) || sum(nl,nr,(t << 1) | 1,mid + 1,r);
    }
};
map<int,int>re;
int offline(vector<vector<box>>&f,vector<box>&v) {
    map<int,int>m;
    for(box &i : v) {
        m.insert({i.a,0});
        m.insert({i.b,0});
    }
    int t = 0;
    for(auto &i : m) {
        re.insert({t,i.first});
        i.second = t++;
    }
    for(box &i : v) {
        i.a = m.find(i.a)->second;
        i.b = m.find(i.b)->second;
    }
    for(auto &i : f) {
        for(box &j : i) {
            j.a = m.find(j.a)->second;
            j.b = m.find(j.b)->second;
        }
    }
    return m.size();
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;cin>>n;
    while(n--) {
        re.clear();
        int n;cin>>n;
        vector<vector<box>>f(n);
        vector<box>v;
        for(int i = 0;i<n;i++) {
            int a,b,c;cin>>a>>b>>c;
            a--;b--;c--;
            if(a > b) swap(a,b);
            f.at(c).push_back(box(a,b,c));
            v.push_back(box(a,b,c));
        }
        int k;
        seg_tree<bool>tt(k = offline(f,v));
        function<int(int,int,int,int)> check = [&] (int l,int r,int v,int t) {
            if(t == -1) t = 1;
            if(l == r) {
                if(tt.exact(t,l,r)) {
                    if(v <= l) {
                        return l;
                    }
                }
                return INT_MAX;
            }
            if(!tt.exact(t,l,r)) return INT_MAX;
            tt.push(t,l,r);
            if(v > r) return INT_MAX;
            int mid = (l + r) >> 1;
            int dt = INT_MAX;
            if(v <= r) {
                if(tt.exact(t << 1,l,mid)) {
                    int tmp = check(l,mid,v,t << 1);
                    if(tmp == INT_MAX) return check(mid + 1,r,v,(t << 1) | 1);
                    else return tmp;
                }
                else return check(mid + 1,r,v,(t << 1) | 1);
            }
            return -1;
        };
        function<int(int,int,int,int)> ck = [&] (int l,int r,int v,int t) {
            if(t == -1) t = 1;
            if(l == r) {
                if(tt.exact(t,l,r)) {
                    if(v >= r) return r;
                }
                return INT_MIN;
            }
            if(!tt.exact(t,l,r)) return INT_MIN;
            tt.push(t,l,r);
            if(v < l) return INT_MIN;
            int mid = (l + r) >> 1;
            int dt = INT_MIN;
            if(v >= l) {
                if(tt.exact((t << 1) | 1,mid + 1,r)) {
                    int tmp = ck(mid + 1,r,v,(t << 1) | 1);
                    if(tmp == INT_MIN) return ck(l,mid,v,t << 1);
                    else return tmp;
                }
                else return ck(l,mid,v,t << 1);
            }
            return -1;
        };
        map<pair<int,int>,int>m;
        for(int i = 0;i<=1;i++) {
            for(auto &i : f) {
                for(box &j : i) {
                    int tmp = check(0,k - 1,j.b,1);
                    auto found = m.find({j.a,j.b});
                    int ans = (found == m.end() ? INT_MAX : found->second);
                    if(tt.sum(j.a,j.b)) ans = 0;
                    else {
                        if(tmp != INT_MAX) ans = min(ans,(abs(re.find(tmp)->second - re.find(j.b)->second)));
                        tmp = ck(0,k - 1,j.a,1);
                        if(tmp != INT_MIN) ans = min(ans,abs(re.find(tmp)->second - re.find(j.a)->second));
                    }
                    m.insert({{j.a,j.b},ans});
                    m.find({j.a,j.b})->second = ans;
                }
                for(box &j : i) {
                    tt.add(j.a,j.b,1);
                }
            }
            reverse(f.begin(),f.end());
            tt = seg_tree<bool>(k);
        }
        for(box &i : v) {
            cout<<m.find({i.a,i.b})->second<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

Codeforces - Multi-Colored-Segments
http://mysh212.github.io/algosolution/Multi-Colored-Segments.cpp/
作者
ysh
發布於
2022年12月3日
更新於
2024年1月12日
許可協議