题目链接:传送门
D. Tree
Add a new node (index
c
n
t
+
1
cnt + 1
cnt + 1) with weight
W
W
W and add edge between node
R
R
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
X
X.
For some nodes
i
,
j
i, j
i, j that are consecutive in the sequence if i is an ancestor of j then
w
[
i
]
≥
w
[
j
]
w[i] ≥ w[j]
w[i] ≥ w[j] and there should not exist a node
k
k
k on simple path from
i
i
i to
j
j
j such that
w
[
k
]
≥
w
[
j
]
w[k] ≥ w[j]
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 Q Q ( 1 ≤ Q ≤ 400000 1 ≤ Q ≤ 400000 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
1
1
p
p
p
q
(
1
≤
p
,
q
≤
1
0
18
)
:
q (1 ≤ p, q ≤ 10^{18}):
q(1 ≤ p, q ≤ 1018): This is query of first type where and . It is guaranteed that
1
≤
R
≤
c
n
t
1 ≤ R ≤ cnt
1 ≤ R ≤ cnt and
0
≤
W
≤
1
0
9
0 ≤ W ≤ 10^9
0 ≤ W ≤ 109.
2
2
2
p
p
p
q
q
q (
1
≤
p
,
q
≤
1
0
18
1 ≤ p, q ≤ 10^{18}
1 ≤ p, q ≤ 1018): This is query of second type where and . It is guaranteed that
1
≤
R
≤
c
n
t
1 ≤ R ≤ cnt
1 ≤ R ≤ cnt and
0
≤
X
≤
1
0
15
0 ≤ X ≤ 10^{15}
0 ≤ X ≤ 1015.
denotes bitwise
X
O
R
XOR
XOR of
a
a
a and
b
b
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
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
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
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
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,
l a s t = 0 last = 0 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. l a s t = 0 last = 0 last = 0
-
Query 3: 2 2 1, Answer is 1 as sequence will be {2}. l a s t = 1 last = 1 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. l a s t = 1 last = 1 last = 1
-
Query 6: 2 3 3, Answer is 2 as sequence will be {3, 2}. l a s t = 2 last = 2 last = 2
题意
给一颗树,每个点都有一个权值,两种操作,一个是在某个节点添加一个儿子节点,另一种是询问一个从 c u r cur cur开始的最长的序列 W W W(用节点表示),记这个序列长度为 l e n len len,这个序列满足如下要求:
-
W [ j ] W[j] W[j]是 W [ i ] W[i] W[i]的一个祖先对任意的 i , j ( j > i ) i,j(j>i) i,j(j>i)成立
-
∑ i = 1 i = l e n v a l [ W [ i ] ] < = X \sum_{i=1}^{i=len}{val[W[i]]}<=X ∑i=1i=lenval[W[i]]<=X
-
∀ i < l e n \forall i<len ∀i<len有 v a l [ W [ i + 1 ] ] > = v a l [ W [ i ] ] val[W[i+1]]>=val[W[i]] val[W[i+1]]>=val[W[i]]从节点 W [ i ] W[i] W[i]路径到 W [ i + 1 ] W[i+1] W[i+1]的简单路径上的权值均小于 v a l [ W [ i ] ] val[W[i]] val[W[i]]
题解:倍增法
可以看出,只需在从 c u r cur cur节点到根节点的简单路径经过的节点中,如果当前节点权值大于等于前一个节点权值,那么这个节点可以取且必须取(不取将不满足第三个要求),然后一直取知道权值大于 X X X或到了根节点。
那么可以用 d p [ c u r ] [ i ] dp[cur][i] dp[cur][i]表示从 c u r cur cur开始的第 2 i 2^i 2i个节点( c u r cur cur不算在内),然后先考虑状态转移:
-
首先找到从 c u r cur cur到根节点的简单路径上的第一个大于 v a l [ c u r ] val[cur] val[cur]的节点
-
然后将该节点的状态转移到 c u r cur cur节点上
附代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 400005;
typedef long long ll;
ll u, w, cnt = 0, x, pre[maxn][21], val[maxn], sum[maxn][21];
ll ans = 0;
int type, m;
int main()
{
scanf("%d", &m);
val[++cnt] = 0;
for(int i = 0; i <= 20; i++) sum[1][i] = 1e18;
val[0] = 1e18;
for(int i = 1; i <= m; i++)
{
scanf("%d %lld %lld", &type, &u, &x);
u ^= ans;
x ^= ans;
if(type == 1)
{
cnt++;
val[cnt] = x;
if(val[u] >= x) pre[cnt][0] = u;
else
{
for(int i = 20; i >= 0; i--)
{
if(val[pre[u][i]] < x)
{
u = pre[u][i];
}
}
pre[cnt][0] = pre[u][0];
}
sum[cnt][0] = !pre[cnt][0] ? 1e18 : val[pre[cnt][0]];
for(int i = 1; i <= 20; i++)
{
pre[cnt][i] = pre[pre[cnt][i - 1]][i - 1];
sum[cnt][i] = !pre[cnt][i] ? 1e18 : sum[pre[cnt][i - 1]][i - 1] + sum[cnt][i - 1];
}
}
else
{
if(x < val[u])
{
printf("0\n");
ans = 0ll;
continue;
}
ans = 1ll;
x -= val[u];
for(int i = 20; i >= 0; i--)
{
if(sum[u][i] <= x)
{
x -= sum[u][i];
ans += (1 << i);
u = pre[u][i];
}
}
printf("%lld\n", ans);
}
}
}