D. Tree(ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined)

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
    starts with R.
    Every node in the sequence is an ancestor of its predecessor.
    Sum of weight of nodes in sequence does not exceed X.
    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 0. last = 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 1. last = 1

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

思路:树上倍增,类似于lca 只不过每一个节点不是跳到2^i个祖先,而是比此节点大的地2^i个祖先,然后找到第一个应该连接的祖先节点,其他就跟lca一样了,顺便维护个sum数组就行
ac代码:

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f3f3f3f
using namespace std;
const int maxn = 4e5+32;
int dp[maxn][32];
LL va[maxn];
LL sum[maxn][32];
int q;
int fa[maxn];
int p = 1;
void  init()
{
    for(int i = 1;i<=q;i++){
        fa[i] = 0;
    }
}
void update(LL pa,LL _va)
{
    ++p;
    va[p] = _va;
    if(va[pa]>=_va){
        dp[p][0] = pa;
    }
    else{
        LL pp = pa;
        for(int i = 31;i>=0;i--){
            if(dp[pp][i] == 0)
                continue;
            if(va[dp[pp][i]]<_va){
                pp = dp[pp][i];
            }
        }
        if(va[dp[pp][0]]>=_va){
            dp[p][0] = dp[pp][0];
        }
    }
    if(dp[p][0]==0){
     //   cout<<"gan"<<endl;
        sum[p][0] = INF;
        return;
    }
    else{
        sum[p][0] = va[dp[p][0]];
    }
    for(int i = 1;i<=31;i++){
        dp[p][i] = dp[dp[p][i-1]][i-1];
        //sum[p][i] = sum[p][i-1]+va[dp[p][i]];
        sum[p][i]=sum[p][i-1]+sum[dp[p][i-1]][i-1];
    }
}
LL getans(LL s,LL li)
{
    if(dp[s][0]==0){
      //  cout<<"gan2"<<endl;
        if(li<va[s]){
            return 0;
        }
        else{
            return 1;
        }
    }
    if(li<va[s]){
        return 0;
    }
    li -= va[s];
    LL ret = 0;
    for(int i = 31;i>=0;i--){
        if(dp[s][i]==0) continue;
        if(sum[s][i]<=li){
            li -= sum[s][i];
            s = dp[s][i];
            ret |= (1<<i);
        }
    }
    return ret+1;
}
int main()
{
    LL last = 0;
    scanf("%d",&q);
    init();
    while(q--){
        int op;
        LL a,b;
        scanf("%d%lld%lld",&op,&a,&b);
        a = last^a;
        b = last^b;
       // cout<<"fuck"<<' '<<a<<' '<<b<<endl;
        if(op==1){
            update(a,b);
        }
        else{

            last = getans(a,b);
            printf("%lld\n",last);
        }
    }
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值