제출 #1369500

#제출 시각아이디문제언어결과실행 시간메모리
1369500gohchingjaykRigged Roads (NOI19_riggedroads)C++20
100 / 100
245 ms102284 KiB
#pragma GCC optimize("O3,inline")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;

using namespace std;

using ll = long long;

#define int ll

using ii = pair<int, int>;
using iii = pair<ii, int>;

constexpr int INF = 1e18 + 5;
constexpr int MAXN = 300000 + 5;
constexpr int MOD = 1e9 + 7;

template <class T>
struct SegTree {
    int n; T id; std::vector<T> seg; std::function<T(T,T)> fn;
    SegTree(int sz=0,T idv=INF,std::function<T(T,T)> f = [](T a,T b){ return min(a,b); }): n(sz),id(idv),fn(f) {
        seg.assign(2*n,id);
    }
    void set(int p,T v) {
        for (seg[p+=n]=v; p>1; p>>=1) seg[p>>1] = fn(seg[p],seg[p^1]);
    }
    T query(int l,int r) {
        T lv=id,rv=id; l+=n; r+=n+1;
        while (l<r) {
            if (l&1) lv = fn(lv,seg[l++]);
            if (r&1) rv = fn(seg[--r],rv);
            l>>=1; r>>=1;
        }
        return fn(lv,rv);
    }
};

struct HLD {
    int n=0,lg=0,root=0,tim=0;
    std::vector<int> par,dep,sz,hv,head,pos;
    std::vector<std::vector<int>> up;
    SegTree<long long> st;

    HLD() = default;
    HLD(const std::vector<std::vector<int>>& adj,const std::vector<long long>& a,int baseRoot=0) { build(adj,a,baseRoot); }

    void build(const std::vector<std::vector<int>>& adj,const std::vector<long long>& a,int baseRoot=0) {
        n=(int)adj.size(); root=baseRoot;
        par.assign(n,-1); dep.assign(n,0); sz.assign(n,0);
        hv.assign(n,-1); head.assign(n,0); pos.assign(n,0);

        std::vector<int> order; order.reserve(n);
        std::vector<int> stk(1,baseRoot);
        while (!stk.empty()) {
            int u=stk.back(); stk.pop_back();
            order.push_back(u);
            for (int v : adj[u]) if (v!=par[u]) {
                par[v]=u; dep[v]=dep[u]+1;
                stk.push_back(v);
            }
        }
        for (int i=(int)order.size()-1;i>=0;i--) {
            int u=order[i], best=0;
            sz[u]=1; hv[u]=-1;
            for (int v : adj[u]) if (v!=par[u]) {
                sz[u]+=sz[v];
                if (sz[v]>best) best=sz[v], hv[u]=v;
            }
        }

        lg=1; while ((1<<lg) <= n) lg++;
        up.assign(lg,std::vector<int>(n,-1));
        for (int u=0;u<n;u++) up[0][u]=par[u];
        for (int j=1;j<lg;j++)
            for (int u=0;u<n;u++)
                up[j][u]= up[j-1][u]==-1 ? -1 : up[j-1][up[j-1][u]];

        tim=0;
        std::vector<std::pair<int,int>> st2(1,{baseRoot,baseRoot});
        while (!st2.empty()) {
            auto [u,h]=st2.back(); st2.pop_back();
            for (int x=u; x!=-1; x=hv[x]) {
                head[x]=h; pos[x]=tim++;
                for (int v : adj[x]) if (v!=par[x] && v!=hv[x]) st2.push_back({v,v});
            }
        }

        st = SegTree<int>(n);
        for (int u=0;u<n;u++) st.set(pos[u],a[u]);
    }

    void setRoot(int r) { root=r; }

	void pointSet(int u, int v) {
		st.set(pos[u], v);
	}

    long long pathMin(int u,int v) {
		long long res=INF;
        while (head[u]!=head[v]) {
            if (dep[head[u]]<dep[head[v]]) std::swap(u,v);
            res = min(res, st.query(pos[head[u]],pos[u]));
            u=par[head[u]];
        }
        if (dep[u]>dep[v]) std::swap(u,v);

        if (pos[u] < pos[v])
			res = min(res, st.query(pos[u] + 1,pos[v]));
        return res;
    }

private:
    int in(int u) const { return pos[u]; }
    int out(int u) const { return pos[u] + sz[u] - 1; }
    bool isAnc(int u,int v) const { return in(u)<=in(v) && in(v)<=out(u); } // u ancestor of v (baseRoot)
    int jump(int u,int k) const {
        for (int j=0;j<lg && u!=-1;j++) if (k>>j&1) u=up[j][u];
        return u;
    }
};

vector<vector<int>> adjlist;
vector<int> labels;
int labelsToNodes[MAXN];
int depth[MAXN];

void dfs1(int x, int pa) {
	for (int ch : adjlist[x]) {
		if (ch == pa) continue;
		depth[ch] = depth[x] + 1;
		dfs1(ch, x);
	}
}

signed main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	
	int N, E; cin >> N >> E;
	adjlist.resize(N);
	labels.resize(N);

	vector<ii> edges(E);
	for (int i = 0; i < E; ++i) {
		int u, v; cin >> u >> v;
		u--, v--;
		edges[i] = ii{u, v};
	}
	
	vector<bool> inUse(E);
	for (int i = 1; i < N; ++i) {
		int x; cin >> x;
		x--;
		inUse[x] = true;
		auto [u, v] = edges[x];
		adjlist[u].emplace_back(v);
		adjlist[v].emplace_back(u);
	}
	
	dfs1(0, -1);
	labels[0] = INF;

	for (int i = 0; i < E; ++i) {
		if (inUse[i]) {
			auto [u, v] = edges[i];
			if (depth[u] < depth[v]) swap(u, v);
			labels[u] = i;
			labelsToNodes[i] = u;
		}
	}
	
	HLD hld(adjlist, labels);

	vector<int> ans(E);
	int ctr = 1;
	for (int i = 0; i < E; ++i) {
		if (ans[i]) continue;
		if (inUse[i]) {
			ans[i] = ctr++;
			auto [u, v] = edges[i];
			if (depth[u] < depth[v]) swap(u, v);
			hld.pointSet(u, INF);
			continue;
		}
		
		int mn;
		while ((mn = hld.pathMin(edges[i].first, edges[i].second)) != INF) {
			ans[mn] = ctr++;
			int u = labelsToNodes[mn];
			hld.pointSet(u, INF);
		}
		ans[i] = ctr++;
	}
	
	for (int i = 0; i < E; ++i) cout << ans[i] << ' ';

}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…