Submission #725800

#TimeUsernameProblemLanguageResultExecution timeMemory
725800PenguinsAreCuteValley (BOI19_valley)C++17
36 / 100
588 ms262144 KiB
// "Always use complex numbers rather than pears." - A Rafflesian Y1
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define re real()
#define im imag()
#define mp make_pair
#define pb push_back
#define speed ios_base::sync_with_stdio(false); cin.tie(0)
#define stMn(a,b) a = min(a,b)
typedef complex<int> ii;
typedef vector<ii> vii;
#define REP(i, a, b) for(int i = a; i < b; i++)
#define MAXN 201210
#define MAXH 19
#define INF 31415926535897932
vii adj[MAXN];
int ctrP[MAXN], sbtree[MAXN], ctrH[MAXN];
int h[MAXN], rtdst[MAXN], pre[MAXN], post[MAXN],sparsetable[2*MAXN][MAXH], fEuler[MAXN], logarithm[2*MAXN], cnt, cnt2;
struct node{
    int s, e, v, mid;
    node *l, *r;
    node(int _s, int _e) {
        s=_s;e=_e;mid=(s+e)>>1;v=INF;
        l = r = nullptr;
    }
    void create() {
        if(s!=e&&!l) {
            l=new node(s,mid);
            r=new node(mid+1,e);
        }
    }
    void update(int x, int u){
        if(s==e) {stMn(v,u);return;}
        create();
        if(x<=mid)l->update(x,u);
        else r->update(x,u);
        v=min(l->v,r->v);
    }
    int query(int x,int y) {
        if(s==x&&e==y)return v;
        if(y<=mid)return (l==nullptr)?INF:l->query(x,y);
        else if(x>mid)return (r==nullptr)?INF:r->query(x,y);
        else return min((l==nullptr)?INF:l->query(x,mid),(r==nullptr)?INF:r->query(mid+1,y));
    }
};
void dfs_reg(int x, int par) {
    pre[x]=cnt++;
    sparsetable[cnt2][0] = h[x];
    fEuler[x] = cnt2++;
    for(auto i: adj[x]) if(i.re != par) {
        h[i.re] = h[x] + i.im;
        rtdst[i.re] = rtdst[x] + 1;
        dfs_reg(i.re, x);
        sparsetable[cnt2++][0]=h[x];
    }
    post[x]=cnt-1;
}
void fnd() {
    logarithm[1] = 0;
    REP(i, 2, 2 * MAXN) logarithm[i] = logarithm[i/2] + 1;
}
void constructST() {
    REP(i, 1, MAXH) REP(j, 0, 2 * MAXN) {
        if(j <= 2 * MAXN - (1<<i)) {
            sparsetable[j][i] = min(sparsetable[j][i-1], sparsetable[j+(1<<(i-1))][i-1]);
        }
    }
}
int lca(int a, int b) {
    if(fEuler[a] > fEuler[b]) swap(a, b);
    int df = fEuler[b] - fEuler[a] + 1;
    int h = logarithm[df];
    return min(sparsetable[fEuler[a]][h],sparsetable[fEuler[b]+1-(1<<h)][h]);
}
int dfs_sb3(int x, int par) {
    sbtree[x] = 1;
    for(auto i: adj[x]) if(i.re != par && ctrH[i.re] == -1) {
        sbtree[x] += dfs_sb3(i.re, x);
    }
    return sbtree[x];
}
int dfs_ctr(int u, int p, int n) {
	for (auto v : adj[u]) if(ctrH[v.re] == -1) {
		if (v.re != p && sbtree[v.re] > n / 2) {
			return dfs_ctr(v.re, u, n);
		}
	}
	return u;
}
void ctr3(int u, int p, int l) {
	int n = dfs_sb3(u, p);
	int cent = dfs_ctr(u, p, n);
	ctrP[cent] = p;
	ctrH[cent] = l;
	for (auto v : adj[cent]) {
		if (ctrH[v.re] != -1) continue;
		ctr3(v.re, cent, l + 1);
	}
}
int32_t main() {
	//speed;
    int n, s, q, e, w, I; cin >> n>>s>>q>>e;
    int a[n],b[n];
    REP(i, 1, n) {
        cin >> a[i] >> b[i] >> w;
        adj[a[i]].pb(ii(b[i],w));
        adj[b[i]].pb(ii(a[i],w));
    }
    REP(i, 0, MAXN) ctrH[i] = -1;
    node *segtree[n+5];
    REP(i, 1, n+1) segtree[i] = new node(0, n-1);
    dfs_reg(e, -1); ctr3(e, -1, 0);
    fnd(); constructST();
    REP(i,0,s) {
        cin>>w;
        int cur = w;
        while(cur != -1) {
            segtree[cur]->update(pre[w], h[cur]+h[w]-2*lca(cur,w));
            cur = ctrP[cur];
        }
    }
    while(q--) {
        cin >> I >> w;
        if(h[a[I]]>h[b[I]]) swap(a[I],b[I]);
        if(pre[b[I]]>pre[w] || post[b[I]]<pre[w]) cout << "escaped\n";
        else {
            int cur = w; int ans = INF;
            while(cur != -1) {
                stMn(ans,segtree[cur]->query(pre[b[I]],post[b[I]])+h[cur]+h[w]-2*lca(cur,w));
                cur = ctrP[cur];
            }
            if(ans<INF)cout << ans << "\n";
            else cout << "oo\n";
        }
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...