Submission #58480

#TimeUsernameProblemLanguageResultExecution timeMemory
58480BenqSpecial graph (IZhO13_specialg)C++14
100 / 100
169 ms41780 KiB

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;
 
typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()

const int MOD = 1000000007;
const ll INF = 1e18;
const int MX = 100001;


template<int SZ> struct DSU {
    int par[SZ], sz[SZ];
    DSU() {
        F0R(i,SZ) par[i] = i, sz[i] = 1;
    }
    
    int get(int x) { // path compression
    	if (par[x] != x) par[x] = get(par[x]);
    	return par[x];
    }
    
    bool unite(int x, int y) { // union-by-rank
    	x = get(x), y = get(y);
    	if (x == y) return 0;
    	if (sz[x] < sz[y]) swap(x,y);
    	sz[x] += sz[y], par[y] = x;
    	return 1;
    }
};

DSU<MX> D;
int N, M, nex[MX][17], bad[MX], depth[MX];
pi cyc[MX]; // #, pos
int cycsz[MX];
set<int> lef[MX];

vector<array<int,3>> q;
vi ret;

void addEdge(int x) {
    D.unite(x,nex[x][0]);
    if (cyc[x].f) lef[cyc[x].f].erase(cyc[x].s);
}

bool con(int t, int y) {
    assert(t != y);
    int co = cyc[t].f;
    t = cyc[t].s, y = cyc[y].s;
    auto it = lef[co].lb(t);
    if (t > y) {
        if (it != lef[co].end()) return 0;
        it = lef[co].begin();
    }
    return it == lef[co].end() || *it >= y;
}

int dis(int t, int y) {
    int cur = cyc[y].s-cyc[t].s;
    if (cur < 0) cur += cycsz[t];
    return cur;
}

int anc(int x, int d) {
    F0Rd(i,17) if (d&(1<<i)) x = nex[x][i];
    return x;
}

int query(int x, int y) {
    if (D.get(x) != D.get(y)) return -1;
    if (depth[x] >= depth[y]) {
        int t = anc(x,depth[x]-depth[y]);
        if (t == y) return depth[x]-depth[y];
    }
    if (depth[y]) return -1;
    int t = anc(x,depth[x]);
    if (con(t,y)) return depth[x]+dis(t,y);
    return -1;
}

int vis[MX];

void solve(int x) {
    int X = x;
    vi cur;
    while (1) {
        // cout << "AH " << x << " " << X << " " << vis[X] << "\n";
        if (X == 0) return;
        if (vis[X] == 0) {
            vis[X] = x;
        } else if (vis[X] == x) {
            vis[X] += N;
            cur.pb(X);
        } else if (vis[X] == x+N) {
            break;
        } else return;
        X = nex[X][0];
    }
    // cout << "OH " << x << " " << sz(cur) << " " << cur[0] << "\n";
    F0R(i,sz(cur)) {
        cyc[cur[i]] = {x,i};
        cycsz[cur[i]] = sz(cur);
        lef[x].insert(i);
    }
}

int getDepth(int x) {
    if (depth[x]) return depth[x];
    if (x == 0  || vis[x] > N) return 0;
    return depth[x] = getDepth(nex[x][0])+1;
}

void process() {
    // cyc, cycsz, lef
    FOR(i,1,N+1) solve(i);
    FOR(i,1,N+1) if (vis[i] <= N) {
        depth[i] = getDepth(i);
       // cout << "BLAH " << i << " " << depth[i] << "\n";
    }
    /*FOR(i,1,N+1) {
        cout << cyc[i].f << " " << cyc[i].s << " " << cycsz[i] << " " << depth[i] << "\n";
    }*/
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    cin >> N;
    FOR(i,1,N+1) {
        cin >> nex[i][0];
        if (nex[i][0] == i) nex[i][0] = 0;
    }
    FOR(i,1,17) FOR(j,1,N+1) nex[j][i] = nex[nex[j][i-1]][i-1];
    process();
    cin >> M;
    F0R(i,M) {
        int t; cin >> t;
        if (t == 1) {
            int a; cin >> a; bad[a] = 1;
            q.pb({1,a,0});
        } else {
            int a,b; cin >> a >> b; 
            q.pb({2,a,b});
        }
    }
    FOR(i,1,N+1) if (!bad[i] && nex[i][0]) addEdge(i);
    reverse(all(q));
    for (auto a: q) {
        if (a[0] == 1) addEdge(a[1]);
        else ret.pb(query(a[1],a[2]));
    }
    reverse(all(ret));
    for (int i: ret) cout << i << "\n";
}

/* Look for:
* the exact constraints (multiple sets are too slow for n=10^6 :( ) 
* special cases (n=1?)
* overflow (ll vs int?)
* array bounds
*/
#Verdict Execution timeMemoryGrader output
Fetching results...