Codeforces 932D Tree 树上倍增

D. Tree
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given a node of the tree with index 1 and with weight 0. Let cnt be the number of nodes in the tree at any instant (initially, cnt is set to 1). Support Q queries of following two types:

  •  Add a new node (index cnt + 1) with weight W and add edge between node R and this node.
  •  Output the maximum length of sequence of nodes which
    1. starts with R.
    2. Every node in the sequence is an ancestor of its predecessor.
    3. Sum of weight of nodes in sequence does not exceed X.
    4. For some nodes i, j that are consecutive in the sequence if i is an ancestor of j then w[i] ≥ w[j]and there should not exist a node k on simple path from i to j such that w[k] ≥ w[j]

The tree is rooted at node 1 at any instant.

Note that the queries are given in a modified way.

Input

First line containing the number of queries Q (1 ≤ Q ≤ 400000).

Let last be the answer for previous query of type 2 (initially last equals 0).

Each of the next Q lines contains a query of following form:

  • 1 p q (1 ≤ p, q ≤ 1018): This is query of first type where  and . It is guaranteed that 1 ≤ R ≤ cnt and 0 ≤ W ≤ 109.
  • 2 p q (1 ≤ p, q ≤ 1018): This is query of second type where  and . It is guaranteed that 1 ≤ R ≤ cnt and 0 ≤ X ≤ 1015.

 denotes bitwise XOR of a and b.

It is guaranteed that at least one query of type 2 exists.

Output

Output the answer to each query of second type in separate line.

Examples
input
Copy
6
1 1 1
2 2 0
2 2 1
1 3 0
2 2 0
2 2 2
output
0
1
1
2
input
Copy
6
1 1 0
2 2 0
2 0 3
1 0 2
2 1 3
2 1 6
output
2
2
3
2
input
Copy
7
1 1 2
1 2 3
2 3 3
1 0 0
1 5 1
2 5 0
2 4 0
output
1
1
2
input
Copy
7
1 1 3
1 2 3
2 3 4
1 2 0
1 5 3
2 5 5
2 7 22
output
1
2
3
Note

In the first example,

last = 0

- Query 1: 1 1 1, Node 2 with weight 1 is added to node 1.

- Query 2: 2 2 0, No sequence of nodes starting at 2 has weight less than or equal to 0last = 0

- Query 3: 2 2 1, Answer is 1 as sequence will be {2}last = 1

- Query 4: 1 2 1, Node 3 with weight 1 is added to node 2.

- Query 5: 2 3 1, Answer is 1 as sequence will be {3}. Node 2 cannot be added as sum of weights cannot be greater than 1last = 1

- Query 6: 2 3 3, Answer is 2 as sequence will be {3, 2}last = 2




给出一棵树,完成两种操作:

1.添加一个带权节点

2.查询从某个节点开始的满足条件的序列最长长度。要求序列当中每个点之后所跟随的是它的祖先节点,且点的权值递增,并且权值总和不超过所给上界。


利用树上倍增可以在O(nlogn)的时间内完成上述操作。

只需开两个数组,fa[x][y]表示x号节点按顺序向上第2^y个权值递增的节点编号,sum[x][y]表示x号节点按顺序向上,一直到第2^y个权值递增的节点,这一串节点的权值和。

增加节点的时候只要找到fa[x][0],就可以用倍增的方法推出所有fa[x][y]。而fa[x][0]要么是它的父亲,要么可以从它的父亲向上爬到达。这里的爬,是指链剖当中向上爬2^k,2^(k-1),....2^0个节点的方法。

由于我们在增加节点的时候,已经使得fa和sum数组满足权值递增的条件,所以查询只要同样的从开始的节点向上爬就好了。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=400005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L);
ll sum[maxn][21],a[maxn];
int fa[maxn][21];
int n=0;

int main() {
	int last=0,q,i,j;
	ll x,y,z;
	scanf("%d",&q);
	memset(fa,-1,sizeof(fa));
	meminf(sum);
	sum[1][0]=a[1]=0;n=1;
	for (j=1;j<=q;j++) {
		scanf("%I64d",&z);
		scanf("%I64d%I64d",&x,&y);
		x^=last;y^=last;
		if (z==1) {
			n++;a[n]=y;
			if (a[x]>=y) {
				fa[n][0]=x;
			} else {
				int now=x;
				for (i=20;i>=0;i--) {
					if (fa[now][i]==-1) continue;
					if (a[fa[now][i]]<y) now=fa[now][i];
				}
				fa[n][0]=fa[now][0];
			}
			int now=fa[n][0];
			if (now==-1) continue;
			sum[n][0]=a[now];
			for (i=1;i<=20;i++) {
				if (fa[now][i-1]==-1) break;
				fa[n][i]=fa[now][i-1];
				sum[n][i]=sum[n][i-1]+sum[now][i-1];
				now=fa[now][i-1];
			}
		} else {
			int ans=1;
			if (a[x]>y) {
				printf("0\n");last=0;
				continue;
			} else y-=a[x]; 
			int now=x;
			for (i=20;i>=0;i--) {
				if (fa[now][i]==-1) continue;
				if (sum[now][i]<=y) {
					ans+=(1<<i);
					y-=sum[now][i];
					now=fa[now][i];
				}
			}
			printf("%d\n",ans);
			last=ans;
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值