Submission #1264598

#TimeUsernameProblemLanguageResultExecution timeMemory
1264598M_W_13Jail (JOI22_jail)C++20
100 / 100
806 ms69080 KiB
#include <bits/stdc++.h>

using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
typedef long long ll;
#define pb push_back
#define st first
#define nd second
const int MAXN = 1 << 18;
const int MAXK = 20;
vector<int> graf[MAXN];
vector<pair<int, int>> przedzialy;
int kt = 0;
pair<int, int> seg[2 * MAXN];
int suma[2 * MAXN];
vector<int> bazy[2 * MAXN];
int konczy[MAXN];
int kop[MAXN];
int skok[MAXN][MAXK];
bool czy[MAXN];
int ilena[MAXN];
int ilekon[MAXN];
int ojc[MAXN];
int depth[MAXN];
int odejm[MAXN];
int ile_pod[MAXN];
int preorder[MAXN];
int jaki[MAXN];
int jakipre[MAXN];
const int INF = 1e9;
int N = 1;
int kt2 = 1;
pair<int, int> pyt[MAXN];
queue<int> jakie;

void kopnij(int v) {
    kop[2 * v] += kop[v];
    seg[2 * v].st += kop[v];
    kop[2 * v + 1] += kop[v];
    seg[2 * v + 1].st += kop[v];
    kop[v] = 0;
}

void upd(int v, int l, int r, int p, int k, int x) {
    // cout << "v = " << v << " p = " << p << " k = " << k << " x = " << x << endl;
    // cout << "seg = " << seg[v].st << " val = " << seg[v].nd << '\n';
    if ((p <= l && r <= k)) {
        // cout << "DOOOOOOOOOOOOOODAAAAAAAAAJ = " << v << '\n';
        seg[v].st += x;
        kop[v] += x;
    }
    else if (r < p || l > k) {

    }
    else {
        kopnij(v);
        int sr = (l + r)/2;
        upd(2 * v, l, sr, p, k, x);
        upd(2 * v + 1, sr + 1, r, p, k, x);
        seg[v] = min(seg[2 * v], seg[2 * v + 1]);
        // cout << "v = " << v << " jakie = " << seg[2 * v].st << " jakie2 = " << seg[2 * v + 1].st << " j = " << seg[2 * v + 1].nd <<'\n';
    }
}

void anal() {
    // cout << "ANNNNNNNNNNNNNNNNNNNNAAAAAAAAAALLLLLLLLLLLLLLLLLL" << endl;
    while (seg[1].st == 0) {
        int v = seg[1].nd;
        // cout << "VAL = " << seg[1].st << '\n';
        v = jakipre[v];
        int i = konczy[v];
        // cout << "ZEEROOOOOOOOOOOOOOOoo v = " << v << " i = " << i << endl;
        if (i > 0) {
            ilekon[i] = 0;
            // cout << "ILENAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = " << ilena[i] << '\n';
            if (ilena[i] == 0 && ilekon[i] == 0) {
                // cout << "PUSSSSSSSSSSSHHHHHHHHHHHHHHHHHHHHHANAL = " << i << '\n';
                ilekon[i] = INF;
                jakie.push(i);
            }
            konczy[v] = 0;
        }
        upd(1, 0, N - 1, preorder[v], preorder[v], INF);
    }
    // cout << "SEGGGGGGG = " << seg[1].st << " GDZIEEE = " << seg[1].nd << '\n';
}

void podziel(int l, int r, int i) {
    l += N;
    r += N;
    while (l < r) {
        if ((l % 2) == 1) {
            bazy[l].pb(i);
            l++;
        }
        if (r % 2 == 0) {
            bazy[r].pb(i);
            r--;
        }
        l /= 2;
        r /= 2;
    }
    if (l == r) {
        bazy[l].pb(i);
    }
}

void upd2(int v, int x) {
    v += N;
    while (v > 0) {
        suma[v] += x;
        if (x > 0) {
            odejm[v] += x;
        }
        if (suma[v] == 0) {
            // cout << "TUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK = " << v << endl;
            for (auto i: bazy[v]) {
                // cout << "i = " << i << '\n';
                ilena[i] -= odejm[v];
                if (ilena[i] == 0 && ilekon[i] == 0) {
                    // cout << "PUSSSSSSSSSSSHHHHHHHHHHHHHHHHHHHHHBAAAAAAAAAAAAAAAZYYYYYYYYYYYY = " << i << '\n';
                    jakie.push(i);
                }
            }
        }
        v /= 2;
    }
}

void dfs(int v, int last) {
    ile_pod[v] = 1;
    depth[v] = depth[last] + 1;
    ojc[v] = last;
    skok[v][0] = last;
    for (int k = 1; k < MAXK; k++) {
        skok[v][k] = skok[skok[v][k - 1]][k - 1];
    }
    for (auto syn: graf[v]) {
        if (syn == last) continue;
        dfs(syn, v);
        ile_pod[v] += ile_pod[syn];
    }
}

void dfs2(int v, int last, int nr, bool c) {
    // cout << "v = " << v << endl;
    preorder[v] = kt2;
    jakipre[kt2] = v;
    kt2++;
    if (c) {
        przedzialy[nr].nd = v;
    }
    else {
        nr = kt;
        przedzialy.pb({v, v});
        kt++;
    }
    jaki[v] = nr;
    pair<int, int> maks = {-1, -1};
    for (auto syn: graf[v]) {
        if (syn == last) continue;
        maks = max(maks, {ile_pod[syn], syn});
    }
    if (maks.nd != -1) {
        dfs2(maks.nd, v, nr, true);
        for (auto syn: graf[v]) {
            if (syn == last || syn == maks.nd) continue;
            dfs2(syn, v, -1, false);
        }
    }
}

int lca(int a, int b) {
    if (depth[a] > depth[b]) {
        swap(a, b);
    }
    int k = MAXK - 1;
    // cout << "XD" << endl;
    while (depth[a] != depth[b]) {
        // cout << "a = " << a << " b = " << b << " k = " << k << endl;
        if ((depth[b] - (1 << k)) >= depth[a]) {
            b = skok[b][k];
        }
        k--;
    }
    // cout << "PLS" << endl;
    if (a == b) return a;
    // cout << "BRUH" << endl;
    k = MAXK - 1;
    while (skok[a][0] != skok[b][0]) {
        if (skok[a][k] != skok[b][k]) {
            a = skok[a][k];
            b = skok[b][k];
        }
        k--;
    }
    return skok[a][0];
}

void rob(int v, int oj, int x) {
    bool c = true;
    while (v != oj) {
        // cout << "v = " << v << endl;
        int nr = jaki[v];
        int w = przedzialy[nr].st;
        if (depth[oj] >= depth[w]) {
            w = oj;
            c = false;
        }
        upd(1, 0, N - 1, preorder[w], preorder[v], x);
        // cout << "UPDDDDDDDDDDDDDDDDDDDDDDDDDD w = " << w << " v = " << v << " x = " << x << endl;
        if (w != oj) {
            v = ojc[w];
        }
        else {
            break;
        }
    }
    if (c) {
        // cout << "UPDDDDDDDDDDDDDDDDDDDDD = oj = " << oj << " x = " << x <<  endl;
        upd(1, 0, N - 1, preorder[oj], preorder[oj], x);
    }
}

void rob2(int v, int oj, int i) {
    bool c = true;
    while (v != oj) {
        int nr = jaki[v];
        int w = przedzialy[nr].st;
        if (depth[oj] >= depth[w]) {
            w = oj;
            c = false;
        }
        podziel(preorder[w], preorder[v], i);
        if (w != oj) {
            v = ojc[w];
        }
        else { 
            break;
        }
    }
    if (c) {
        podziel(preorder[oj], preorder[oj], i);
    }
}

void usun(int i) {
    int a = pyt[i].st;
    int b = pyt[i].nd;
    upd2(preorder[a], -1);
    int oj = lca(a, b);
    // cout << "UPDDDDDDDDDDDDDDDDDDDDD2222 = oj = " << oj << " x = " << 1 <<  endl;
    upd(1, 0, N - 1, preorder[oj], preorder[oj], 1);
    if (b != oj) {
        b = ojc[b];
        rob(b, oj, -1);
    }
    rob(a, oj, -1);
    anal();
}

void dod(int i) {
    int a = pyt[i].st;
    int b = pyt[i].nd;
    // cout << "a = " << a << endl;
    upd2(preorder[a], 1);
    // cout << "b = " << b << endl;
    int oj = lca(a, b);
    // cout << "UPDDDDDDDDDDDDDDDDDDDDD3333333 = oj = " << oj << " x = " << -1 <<  endl;
    upd(1, 0, N - 1, preorder[oj], preorder[oj], -1);
    // cout << "G" << endl;
    if (b != oj) {
        b = ojc[b];
        // cout << "b = " << b << " ojc = " << oj << endl;
        rob(b, oj, 1);
    }
    // cout << "SPK" << endl;
    rob(a, oj, 1);
}

int szuk(int a, int oj) {
    int k = MAXK - 1;
    while (skok[a][0] != oj) {
        if ((depth[a] - (1 << k)) > depth[oj]) {
            a = skok[a][k];
        }
        k--;
    }
    return a;
}

void dziel(int i) {
    int a = pyt[i].st;
    int b = pyt[i].nd;
    // cout << "a = " << a << " b = " << b << endl;
    int oj = lca(a, b);
    // cout << "oj = " << oj << endl << '\n';
    // cout << "a = " << a << " b = " << b << " oj = " << oj << endl;
    if (oj != a) {
        a = ojc[a];
        rob2(a, oj, i);
    }
    // cout << "G" << endl;
    if (oj != b) {
        rob2(b, szuk(b, oj), i);
    }
    // cout << "KONIEC" << endl;
}

void solve() {
    int n;
    cin >> n;
    N = 1;
    kt2 = 1;
    kt = 0;
    przedzialy.clear();
    while (N <= n) N *= 2;
    // cout << "N = " << N << '\n';
    rep(i, N) {
        seg[i + N] = {0, i};
        jakipre[i] = i;
        preorder[i] = i;
    }
    for (int i = N - 1; i >= 1; i--) {
        seg[i] = min(seg[2 * i], seg[2 * i + 1]);
    }
    rep(i, n - 1) {
        int a, b;
        cin >> a >> b;
        graf[a].pb(b);
        graf[b].pb(a);
    }
    depth[1] = 0;
    dfs(1, 1);
    dfs2(1, 1, 0, false);
    // cout << "XD" << endl;
    // rep(i, n) {
    //     cout << "v = " << i + 1 << " jaki = " << jaki[i + 1] << " przedzial = " << " l = " << przedzialy[jaki[i + 1]].st << " r = " << przedzialy[jaki[i + 1]].nd << '\n';
    // }
    int m;
    cin >> m;
    rep(i, m) {
        ilena[i + 1] = 0;
        ilekon[i + 1] = 0;
    }
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        pyt[i + 1] = {a, b};
        // cout << "i = " << i << endl;
        dziel(i + 1);
        konczy[b] = i + 1;
        ilekon[i + 1] = INF;
        czy[a] = true;
    }
    // cout << "SKULL" << endl;
    rep(i, m) {
        // cout << "i = " << i << endl;
        dod(i + 1);
    }
    rep(i, 2 * N) {
        for (auto j: bazy[i]) {
            ilena[j] += odejm[i];
        }
    }
    // cout << "FR" << endl;
    anal();
    // cout << "PLS" << endl;
    int s = 0;
    while (!jakie.empty()) {
        int i = jakie.front();
        jakie.pop();
        // cout << "PEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEETLAAAAAAA i = " << i << '\n';
        s++;
        usun(i);
    }
    rep(i, 2 * N) {
        czy[i] = false;
        graf[i].clear();
        konczy[i] = 0;
        odejm[i] = 0;
        depth[i] = 0;
        ile_pod[i] = 0;
        seg[i] = {0, 0};
        bazy[i].clear();
        suma[i] = 0;
        ilena[i] = 0;
        ilekon[i] = 0;
        ojc[i] = 0;
        preorder[i] = 0;
        jaki[i] = 0;
        kop[i] = 0;
    }
    if (s == m) {
        cout << "Yes" << '\n';
        return ;
    }
    cout << "No" << '\n';
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int t;
	cin >> t;
	while(t--) {
		solve();
	}
	return 0;
}
#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...