CF932D Tree 树上倍增
Posted kaka0010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF932D Tree 树上倍增相关的知识,希望对你有一定的参考价值。
原题链接:https://codeforces.com/contest/932/problem/D
题意
一开始有一个初始节点1,权值为0,接下来会有一系列操作:
- R W 将第cnt个节点挂在第R个节点上,权值为W
- R W,询问从R开始的节点往上,如果遇到大于它的权值就加进来,总权值不能超过W,问能加进来多少个
分析
这题和 城市网络非常像,只不过这题是动态加点而已。
但这里多了一个限制,就是总权值之和。我们在记录倍增数组求祖先的时候,可以直接把权值也一起统计,记录 s u m [ i ] [ j ] sum[i][j] sum[i][j]代表从i节点开始,到第 2 j 2^j 2j个祖先位置的权值和。
那么转移方程和倍增找祖先是类似的
s u m [ i ] [ j ] = s u m [ i ] [ j − 1 ] + s u m [ f [ i ] [ j − 1 ] [ j − 1 ] sum[i][j]=sum[i][j-1]+sum[f[i][j-1][j-1] sum[i][j]=sum[i][j−1]+sum[f[i][j−1][j−1]
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ul;
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 5e5 + 10;
const int M = 1e6 + 10;
const ll mod = 1e9 + 7;
const double eps = 1e-8;
#define lowbit(i) (i & -i)
#define Debug(x) cout << (x) << endl
#define fi first
#define se second
#define mem memset
#define endl '\\n'
int f[N][25], a[N];
ll sum[N][25];
inline void solve() {
int n, m; cin >> n;
int cnt = 1;
ll last = 0;
for (int i = 1; i <= n; i++) {
ll opt, x, w; cin >> opt >> x >> w;
x ^= last;
w ^= last;
if (opt == 1) {
++cnt; a[cnt] = w;
if (a[cnt] <= a[x]) {
f[cnt][0] = x;
sum[cnt][0] = a[x];
}
else {
int now = x;
for (int j = 20; ~j; j--) {
if (f[now][j] && a[f[now][j]] < w) {
now = f[now][j];
}
}
f[cnt][0] = f[now][0];
sum[cnt][0] = a[f[now][0]];
}
for (int j = 1; j <= 20; j++) {
f[cnt][j] = f[f[cnt][j-1]][j-1];
sum[cnt][j] = sum[cnt][j-1] + sum[f[cnt][j-1]][j-1];
}
} else {
if (a[x] > w) {
cout << (last = 0) << endl;
continue;
}
w -= a[x];
int now = x;
ll ans = 1;
for (int j = 20; ~j; j--) {
if (f[now][j] && w >= sum[now][j]) {
w -= sum[now][j];
now = f[now][j];
ans += (1 << j);
}
}
cout << (last = ans) << endl;
}
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
以上是关于CF932D Tree 树上倍增的主要内容,如果未能解决你的问题,请参考以下文章