P3899|主席树+dfs序
理解题意后分两种情况: 1.b在a的上方: min(dep[p]-1,k)*(ll)siz[p] 因为(p点上方肯定有父亲结点b,我们不用管b是谁) 2.b在a的下方: (dep(p)+1 ~ dep(p)+k矩形框内的所有点子树个数和 所以思路:主席树维护同一深度下的各个结点子树个数和;下标是深度,权值维护的是子树个数和;在dfs序in和out时间戳上建立主席树,把树上问题转变为区间序列问题,利用dfs序时间戳的性质(子树编号在入时间戳和出时间戳的区间内),查询以p为根子树;所以问题就转变为了查询时间戳内区间内距离为k的点权和(相当于查询 矩形框 框住部分的点的个数了)。用线段树维护貌似也是可以的。 #include<bits/stdc++.h> using namespace std; typedef long long ll; int n,q; const int maxn = 3e5+10; vector<int> g[maxn]; int depth[maxn]; ll size[maxn]; int e = 0; int in[maxn],out[maxn],root[maxn]; int ma_siz[maxn],ma_dep[maxn]; struct Node{ ll v; int lc,rc; }T[maxn*24]; //递归计算dfs序 size子树大小