题目:
【问题描述】
二叉树是一种常用的数据结构,一个二叉树或者为空,或者由根节点、左子树、右子树
构成,其中左子树和右子树都是二叉树. 每个节点 a 可以存储一个值 va.
显然,如果一个点 a 的左子树或右子树内有一个点 b,那么存在唯一的路径从 a 出发,
每次往左子树或右子树走,经过一系列节点访问到 b. 我们把从 a 到 b 经过除 a 以外的节
点数称为节点 a 到节点 b 的距离.
例如对于下图的二叉树, 1 为根节点, 5 在 1 的子树内,从 1 到 5 存在唯一的路径:
1 ! 2 ! 5,经过的除 1 外的节点有 2 个: 2; 5,因此节点 1 到节点 5 的距离为 2.
对于一个点 a,定义:
·若点 b 在 a 的左子树中,且 a 到 b 的距离为 vb,则称 b 为 a 的左关联点;
·若点 b 在 a 的右子树中,且 a 到 b 的距离为 vb,则称 b 为 a 的右关联点.
给定一个共有 n 个节点的二叉树,所有节点编号为 1; 2; :::; n,其中 1 为根节点. 给出
每个节点 a 存储的值 va,请输出每个节点的左关联点个数和右关联点个数.
【输入格式】
输入文件名为 node.in
第一行一个正整数 n,表示二叉树的总节点数.
第二行 n 个由空格分隔的正整数 v1; v2; :::; vn,第 i 个数 vi 表示节点 i 存储的值.
接下来 n 行,第 i 行为两个由空格分隔的整数,分别表示编号为 i 的左子树的根节点
(若左子树为空则为 0)和右子树的根节点(若右子树为空则为 0) .
【输出格式】
输出文件名为 node.out
输出 n 行,第 i 行为两个整数,分别表示点 i 的左关联点个数和右关联点个数.
【样例输入】
5
2 1 3 2 1
2 3
4 5
0 0
0 0
0 0
【样例输出】
2 0
0 1
0 0
0 0
0 0
【样例说明】
节点 1 的左关联点有 2 个: 2 和 4,没有右关联点.
节点 2 没有左关联点,右关联点有 1 个: 5.
除此之外,其它节点没有关联点.
【数据规模与约定】
对于 30% 的数据, n ≤ 3.
对于 60% 的数据, n ≤ 500.
对于 100% 的数据, n ≤ 200000, 1 ≤ vi ≤ 200000,根节点 1 到任意节点的距离不超
过 100000.
思路:
很明显一倍增。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 50000000
#define ll long long
#define read(x) scanf("%lld",&x)
#define md 1000000007
#define lowbit(x) x&-x;
ll n,m,a,b,c;
bool f[maxn+5];
int main() {
read(n),read(m),read(a),read(b),read(c);
ll x=0,ans1=0,ans2=0,cnt1=0,cnt2=0;
for(int i=1;i<=m;i++) {
x=(a*x+b)%(2*c*n);
int id;
if(x<n*c) {
id=x/c+1;
if(!f[id]) {
f[id]=true;cnt1++,cnt2+=id;
}
} else {
id=x/c-n+1;
if(f[id]) {
f[id]=false;cnt1--,cnt2-=id;
}
}
ans1=(ans1+cnt1)%md,ans2=(ans2+cnt2)%md;
}
printf("%d %d",ans1,ans2);
return 0;
}