233

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 1E5 + 10;

int n,m,d_t,cnt,Root,k,anc[maxn][20],root[maxn],L[maxn],in[maxn],out[maxn];
int c[maxn*25],lc[maxn*25],rc[maxn*25],atk[maxn];

vector <int> v[maxn];

void dfs(int x)
{
	in[x] = ++d_t;
	for (int i = 0; i < v[x].size(); i++) {
		int to = v[x][i];
		L[to] = L[x] + 1;
		dfs(to);
	}
	out[x] = d_t + 1;
	for (int i = 1; i < 20; i++) 
		anc[x][i] = anc[anc[x][i-1]][i-1];
}

int Insert(int o,int l,int r,int pos,int add)
{
	int ret = ++cnt;
	c[cnt] = c[o] + add;
	if (l == r) return ret;
	int mid = (l+r) >> 1;
	if (pos <= mid) lc[ret] = Insert(lc[o],l,mid,pos,add),rc[ret] = rc[o];
	else rc[ret] = Insert(rc[o],mid+1,r,pos,add),lc[ret] = lc[o];
	return ret;
}

int LCA(int p,int q)
{
	if (L[p] < L[q]) swap(p,q);
	int Log;
	for (Log = 0; L[p] - (1<<Log) >= 0; Log++); Log--;
	for (int j = Log; j >= 0; j--)
		if (L[p] - (1<<j) >= L[q])
			p = anc[p][j];
	if (p == q) return p;
	for (int j = Log; j >= 0; j--)
		if (anc[p][j] != anc[q][j])
			p = anc[p][j], q = anc[q][j];
	return anc[p][0];
}

int getanc(int x,int y)
{
	int now = 0;
	for (;;) {
		if ((1<<now) > y) return x;
		if (y & (1<<now)) x = anc[x][now];
		++now;
	}
}

int cal(int o1,int o2,int l,int r,int pos)
{
	if (!pos) return 0;
	if (r <= pos) return c[o2] - c[o1];
	int mid = (l+r) >> 1;
	int ret = cal(lc[o1],lc[o2],l,mid,pos);
	if (pos > mid) ret += cal(rc[o1],rc[o2],mid+1,r,pos);
	return ret;
}

bool solve1(int from,int to,int x,int y)
{
	while (L[from] - L[to] > 1) {
		int mid = (L[from]+L[to]) >> 1;
		int sum = L[from] - mid + 1;
		mid = getanc(from,L[from] - mid);
		sum = sum - cal(root[x],root[y],1,n,in[from]) + cal(root[x],root[y],1,n,in[anc[mid][0]]);
		if (atk[from] <= y) --sum;
		if (sum == k) {
			if (atk[mid] <= x) {
				printf("%d\n",mid); 
				return 1;
			}
			else to = mid;
		}
		else if (sum < k) k -= sum,from = mid;
		else to = mid;
	}
	return 0;
}

bool solve2(int from,int to,int x,int y)
{
	while (L[to] - L[from] > 1) {
		int mid = (L[to]+L[from]) >> 1;
		int sum = mid - L[from];
		mid = getanc(to,L[to]-mid);
		sum = sum - cal(root[x],root[y],1,n,in[mid]) + cal(root[x],root[y],1,n,in[from]);
		if (sum == k) {
			if (atk[mid] <= x) {
				printf("%d\n",mid);
				return 1;
			}
			else k -= sum,to = mid;
		}
		else if (sum < k) k -= sum,from = mid;
		else to = mid;
	}
	return 0;
}

int main()
{
	#ifdef YZY	
		freopen("yzy.txt","r",stdin);
	#else
		freopen("path.in","r",stdin);
		freopen("path.out","w",stdout);
	#endif
	
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int x; scanf("%d",&x);
		if (!x) Root = i;
		else anc[i][0] = x,v[x].push_back(i);
	}
	L[Root] = 1; dfs(Root);
	cin >> m;
	for (int i = 1; i <= m; i++) {
		int t,a,b,y; scanf("%d",&t);
		if (t == 1) {
			scanf("%d",&a);
			root[i] = Insert(root[i-1],1,n,in[a],1);
			root[i] = Insert(root[i],1,n,out[a],-1);
			atk[a] = i;
		}
		else {
			root[i] = root[i-1];
			scanf("%d%d%d%d",&a,&b,&k,&y);
			int lca = LCA(a,b);
			if (a != lca) 
				if (solve1(a,lca,y,i))
					continue;
			if (b != lca) {
				bool flag;
				if (a == lca) flag = solve2(lca,b,y,i);
				else flag = solve2(anc[lca][0],b,y,i);
				if (flag) continue;
			}
			printf("-1\n");
		}
	}
	return 0;
}

你可能感兴趣的:(233)